Microsoft Graph API OAuth2でSPAからフローを開始してバックエンド(Rails)でWebアプリ用トークンを受け取る
Microsoft Graph APIのOAuth2を用いてMSプラットフォームのリソースを扱いたいとき、SPAとRailsバックエンドの構成で少々工夫が必要だったため、書いておきたいと思います(他プラットフォームのOAuth2でも同様にできるかもしれません)。
要件としてはSPAからOAuth2のフローを開始して、バックエンドでWebアプリ用のトークンを受け取りたいというものです。SPAからGraph APIを扱う用途向けにはMicrosoftがMSAL.jsというものを公開しており、最初はこれが使えるのでは?と思ったのですがSPA向けのトークンはリフレッシュトークンの有効期限が24時間しかなく今回やりたいことには不向きでした。
色々と調査した結果、Webアプリ用のトークン(リフレッシュトークンの有効期間90日間)を受け取るにはバックエンドのRailsでOmniAuthを用いてOAuth2のフローを実装するしか方法はなさそうです。そこでomniauth-microsoft_graphを用いてバックエンドのみでOAuth2のフローを実装しました。そしてフローを起動する画面をポップアップで開く処理をSPAに実装します。
と、ここまでは順調だったのですが、SPAはAPIのトークン認証を用いてバックエンドとやり取りしており、OAuth2のコールバックを受け取るエンドポイントではログイン中のユーザーを取得できません。そこで、コールバックで取得したトークンを一度セッションに保存し、SPAからAPIリクエストを送ることでそのセッションをユーザーに紐づけられるようにしました(SPAとバックエンドでCookieは共有されています)。
このとき、バックエンドのAPIコールにfetchを使っているのですが、fetchはデフォルトではセッション(Cookie)を送信しません。セッションを送信するには credential: "include"
オプションを設定してやる必要があり、さらにバックエンドのCORSにて、ワイルドカードではなくホスト名の指定、また、Access-Control-Allow-Credentials: true
ヘッダの指定が必要です[1]。この辺りはrack-corsの設定で可能でした。
けっこう多くのYak Shavingが必要でしたが、これで無事SPAからOAuth2フローを開始してバックエンドで有効期限の長いトークンを受け取りユーザーと紐づけることができました。
Discussion