Help us understand the problem. What is going on with this article?

Microsoft GraphでOAuthのアクセストークンを更新する仕組みを作る

More than 1 year has passed since last update.

背景

MicrosoftのOffice365にあるExcel OnlineのシートをAPI経由で更新したい
->そのためには当然Office365へのログイン(認証)が必要
さらに、一度の認証だけでは足りなくて、認証を維持する仕組みが必要(理由は後述)

そこで今回はOAuth認証からトークンの更新をする仕組みの作り方について書きます。

この記事の内容

この記事では
1.Microsoft Graph(Office365を触るためのAPI?)のアプリ作成からOAuth認証の方法
2.アクセストークンの取得方法
3.期限が切れた場合のアクセストークンの更新方法
をまとめます。

前提・環境

Oauth認証部分にはPython3系とflask
処理にはAWSのLambda(Python2.7)を、データの保存にはAWSのDynamoDBを使ってます

OAuth認証の仕組みはざっくり知ってる程度の知識で書いていますので、手順が間違っていたり・飛ばしていたりする可能性があります。その際はご指摘いただけるとありがたいです。

1.アプリの作成からOAuth認証まで

1-1.アプリの登録

アプリを Azure AD v2.0 エンドポイントに登録する
このページを参考にアプリを新規登録して、「アプリケーション ID」と「アプリケーション シークレット」をメモしておきます。

ここでの注意点

↓Microsoft Graph のアクセス許可で必ずoffline_accessをスコープに入れること
これをスコープに入れないと後述するrefresh tokenが返って来ません。
(refresh tokenが無いとアクセストークンの有効期限が切れるたびに手作業(ブラウザ)での認証が必要になる?)

アクセス許可

1-2.OAuth認証

Microsoft Graph アプリの構築を開始する
こちらのページで各言語でのサンプルソースが置いてあります。

今回はPythonを使いましたのでこちらです。

認証までの流れ

GithubのREADMEに記載している流れそのままですが

  • 上のソースをgit cloneしてソースを持って来る
  • 必要なパッケージをpipでインストール
  • READMEに書いている設定↓をして
  • flaskを実行してローカルにWebサーバーを立てる
  • アクセスしてOAuth認証の動作確認

といった感じです。
解説するまでもないかもしれませんが、一つずつ見ていきます。

1.git cloneする

git clone https://github.com/microsoftgraph/python3-connect-rest-sample.git

2.必要なモジュールをpipでインストール(オプション)

もしも5まで進めて no module named ~~といったエラーが出た場合は
pip intall ~~で必要なモジュールを入れてください。

3.READMEに書いている設定をする

README和訳
1.好きなエディタで_PRIVATE.txtを開いて
2.ENTER_YOUR_CLIENT_IDという文字の部分を1-1でメモしたアプリケーション IDに書き換えて
3.ENTER_YOUR_SECRETという文字の部分を1-1でメモしたアプリケーションシークレットに書き換えて

4.flaskを実行してローカルにWebサーバーを立てる

README和訳
4.python manage.py runserver ってコマンド打ってね
5.http://localhost:5000/ にアクセスしたらOAuth認証するためのページが開くよ

5.動作確認

http://localhost:5000/ にアクセスした時にこんな画面が出たら、起動は成功です。
flask

認証をした後は↓こんな画面になって
認証後

Send mailボタンを押した時にメールが飛んでくればOAuth認証成功です。

2.アクセストークンの取得

ここまででOAuth認証は成功しました。
ここからはその認証情報を維持する方法を書いていきます。

上のflaskのソース内にアクセストークンを使っている場所があるので、そこでprintをしてaccess_tokenとrefresh_tokenを可視化します。

connectsample.py 内の80行目あたりに下記を追加するとターミナルに二つのトークンが表示されますので、メモしておきます。

add_to_connectsample
print(response['access_token'])
print(response['refresh_token'])

3.期限が切れた場合のアクセストークンの更新方法

アクセストークンには有効期限があります。その有効期限が切れた後は、アクセストークンの更新が必要です。

更新トークンを使用して新しいアクセス トークンを取得する

今回はアクセストークンとリフレッシュトークンをDynamoDBに保存しておいて、利用時に更新&取り出しを行うようにしました。

3-1.DynamoDBの準備

DynamoDB
こんな感じでテーブルを作っておきます。(usernameと書いたつもりがusenameになってました。)
andoとなっているところは一意に判定できる名前を入れておいてください。

access_token と refresh_tokenには上で取得したものを保存しておいてください。

3-2.Lambdaの準備

getaccess_token.py
# coding:utf-8
import os
import boto3
import json
from boto3.dynamodb.conditions import Key, Attr
import requests

client_id = 'アプリケーション ID'
client_secret = 'アプリケーション シークレット'
username = 'ando'

def get_access_token():
    dynamodb = boto3.resource('dynamodb')
    table    = dynamodb.Table('excelOnlineToken')

    response = table.query(
        KeyConditionExpression=Key('usename').eq(username), Limit=1)
    refresh_token = response['Items'][0]['refresh_token']
    headers = { 'Accept' : 'application/json',
                'Content-Type' : 'application/x-www-form-urlencoded'
                }

    payload = {'client_id': client_id, 'scope': 'User.Read Mail.Send offline_access Files.ReadWrite.All','refresh_token':refresh_token,'redirect_uri':'http://localhost:5000/login/authorized','grant_type':'refresh_token','client_secret':client_secret}

    response = requests.post(
        'https://login.microsoftonline.com/common/oauth2/v2.0/token',
        headers=headers,data=payload)
    jsonObj =  json.loads(response.text)


    table.update_item(
        Key={
            'usename': 'ando'
        },
        UpdateExpression='SET refresh_token = :val1,access_token = :val2',
        ExpressionAttributeValues={
            ':val1': jsonObj["refresh_token"],
            ':val2': jsonObj["access_token"]
        }
    )

    return jsonObj["access_token"]

このLambdaを実行すればMicrosoft GraphにアクセスをしてDynamo内のアクセストークン・リフレッシュトークンを更新して、最新のアクセストークンを返してくれます。

最後に

今回はアクセストークンの期限が切れているかどうかの判定をせずに毎回更新しちゃってますが、期限が切れていた場合のみ更新という風にした方が良さそうですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした