OAuth認証を使ってMicrosoft GraphAPIを利用する



##はじめに
Microsoft GraphAPIを使ってみたメモです。(以下MSGRAPH)
Ubuntu18.04,Python3,Flaskを使っています。
またMicrosoft Graphの利用にはOffice365のアカウントが必要です。

IT企業に入社しましたが運用系にいるため開発は趣味として行っています。
まだプログラミング経験も半年だけなので分からないこと、間違ったことたくさんあると思うので
ご指導、ご指摘の程よろしくお願いします。

##やりたいこと
**MSGRAPHを使うためにOAuth認証を実装する**
OAuth認証が何なのか、APIが何なのかよく分かってないですがとりあえずやってみました。
基本的には[GitHub - Python authentication samples for Microsoft Graph](https://github.com/microsoftgraph/python-sample-auth)を参考にやってます。

##実施したこと
**・Flask-OAuthライブラリをインストールする**

```
pip install Flask-OAuth
```

・AzureADにアプリケーションを登録する
MSGRAPHを使うにはAzureADにアプリケーションを登録する必要があります。
登録の仕方は「[アプリを Azure AD v2.0 エンドポイントに登録する](https://developer.microsoft.com/ja-jp/graph/docs/concepts/auth_register_app_v2)」を見てください。
ここでシークレットIDとパスワードを取得してください。

*2019/01/03更新*
アプリケーションの登録方法についても書かせていただきました
→[AzureADへのアプリケーション登録ってどうやるの？](https://qiita.com/ta9ma_0k/items/998f616f86af528253e1)


**・実装する**
処理の流れは
1．ホーム画面　→　サインインボタン押下
2．サインイン処理　→　アカウント情報入力
3．認証成功画面　→　喜ぶ
とします。

OAuthを使ってリモートアプリケーションを使うためには、OAuthオブジェクトを作成し、remote_app()を使ってアプリケーションを登録します。
'consumer_key'と'consumer_secret'に先ほど取得したIDとパスワードを設定します。(Config.py的なのから呼び出しましょう)
request_token_paramsに設定するパラメータはAzureADへのアプリケーション登録時に設定した権限をいれてください。(APIに必要な権限を登録する)

```python:app.py
import flask
from flask_oauthlib.client import OAuth

APP = flask.Flask(__name__,template_folder='static/templates')
OAUTH = OAuth(APP)
MSGRAPH = OAUTH.remote_app(
        'microsoft',
        consumer_key="先ほどの手順で取得したID",
        consumer_secret="パスワード",
        request_token_params={'scope':'User.Read'},
        base_url='https://graph.microsoft.com/v1.0/',
        request_token_url=None,
        access_token_method='POST',
        access_token_url='https://login.microsoftonline.com/common/oauth2/v2.0/token',
        authorize_url='https://login.microsoftonline.com/common/oauth2/v2.0/authorize'
        )
```

次にサインインボタンが押されたときの処理を記述します。

```python:app.py
@APP.route('/login')
def login():
    flask.session['state']=str(uuid.uuid4())
    return MSGRAPH.authorize(callback='http://localhost:5000/login/authorized',state=flask.session['state'])

@APP.route('/login/authorized')
def authorized():
    if str(flask.session['state']) != str(flask.request.args['state']):
        raise Exception('ERRRRRRRRRRRRRRRRRRRRRR')
    response = MSGRAPH.authorized_response()
    flask.session['access_token'] = response['access_token']
    return flask.redirect('/user')

@APP.route('/user')
def user():
    user_profile=MSGRAPH.get('me',headers=request_headers()).data
    user_name=user_profile['displayName']
    return flask.render_template('user.html',
                                name=user_name,
                                )
```
サインボタンが押されたら、
login()→authorized()→user()
の順で関数が実行されます。

login()内でMSGRAPH.authorize()を呼び出してリモートアプリケーションと接続します。
MSGRAPH.authorize()の結果はauthorized()に渡され、MSGRAPH.authorized_response()によって取得できます。
認証成功時にアクセストークンを保持しておくことで、APIを利用していきます。

user()でMSGRAPHのGETメソッドを使いアカウント情報を取得します。
アカウントの表示名が取得できればOK
GETメソッドを使うためにtokengetterも定義しときます。

```python:app.py
@MSGRAPH.tokengetter
def get_token():
    return (flask.session.get('access_token'),'')
```

2019/01/13
request_headers()について追記しました。

```python:app.py
def request_headers(headers=None):
    default_headers={'SdkVersion':'develop-by-flask',
                     'x-client-SKU':'develop-by-flask',
                     'client-request-id':str(uuid.uuid4()),
                     'return-client-request-id':'true'}
    if headers:
        default_headers.update(headers)
    return default_headers
```

default_headers()はヘッダーを返す関数でMSGRAPH.get実行時に引数内で呼び出しています。
get_token()アクセストークンを返す関数でMSGRAPH.get実行したとき内部的に呼び出されています。
トークン情報からリクエストを実行するクライントを生成しています。



**・テストする**

```
python3 app.py
```
[http://localhost:5000/](http://localhost:5000/)にアクセスします。
![Screenshot from 2018-11-13 20-51-53.png](https://qiita-image-store.s3.amazonaws.com/0/314548/6dc8463c-d635-e26e-e1b8-a4f6dfd1dba6.png)

OAuth認証したいをクリック
サインイン画面が表示されます。
![Screenshot from 2018-11-13 20-53-39.png](https://qiita-image-store.s3.amazonaws.com/0/314548/7cec3218-ca4b-f862-ed5d-8bad360cb2e9.png)

認証成功！！
![Screenshot from 2018-11-13 20-54-18.png](https://qiita-image-store.s3.amazonaws.com/0/314548/2004ba25-8eec-0d6e-cc3e-02108f20d332.png)


##おわりに

Microsoft Graphの開発楽しい

**・参考**
[Flask-OAuthlib](https://flask-oauthlib.readthedocs.io/en/latest/)
[GitHub - Python authentication samples for Microsoft Graph](https://github.com/microsoftgraph/python-sample-auth)
[Python アプリで Microsoft Graph を使ってみる](https://developer.microsoft.com/ja-jp/graph/docs/concepts/python)