LoginSignup
2
1

More than 1 year has passed since last update.

複数のOpenID Connect認証を(Google/Azure/Yahoo)、ExpressとPassportによる実装クライアントで試してみる

Last updated at Posted at 2021-12-11

概要

複数のサービス(Google/Azure/Yahoo)が提供する、OpenID Connect(以下、「OIDC」と略記)のIdentity Provider(以下、「IdP」と略記)に対して、次の2つを説明する。なお、ここでは対象サービスとして「無償で試用が可能なもの」を選んでいる。

  1. 実際にIdP側に設定・登録する内容と、各サービスごとの操作手順
  2. Relying Party(以下「RP」と略記)側への反映方法

その目的は、「OIDCのIdP提供元によってIdP側の設定手順や呼称が異なるが、それをOIDCのクライアントID、シークレットキーに注目して実際のIdp側の操作画面の紐づけること」である。

本記事ではRP側の実装は同一とし、認証要求先のIdPの設定に応じて「それぞれのOIDC認証が動作すること」を検証する。PR側は、Node.jsのExpressを使ったWebページ上にPassportを使って簡単に実装したサンプルを用いる。

本記事で用いるRP側のサンプルコードは、以下を参照。

なお上記の「RPのサンプルコード」は、以下の記事で作成したモノをベースに、複数IdPの情報を設定するために少し修正したものである。設計はほぼ同一なので説明は省略する。

※既にRPを作成済みであり、読み替えが出来るのであれば、本サンプルを利用する必要はない。
※本サンプルは試行であり、それぞれのログインボタンが押下された瞬間にPassportのStrategyをGoogle/Azure/Yahooへ切り替えて、それぞれのOIDC認証が終了するまでに他のアクセスが【来ないことを前提とする】実装、であることに注意。

本記事は以下を前提とする。

  • 認証フローは「認可コードフロー」を使う
    • RFC 6749, 4.1. Authorization Code Grant
  • IDトークンの取得には「POST形式」を使う
    • RFC6749, 9. Client Authentication にある client_secret_post
  • OIDCのIDプロバイダーとして、無償で試用が可能な以下について試行する

RPのサンプルコードで利用するライブラリは以下。

補足(無料で試行が可能の件について)

Azureでは、アカウント作成時に個人確認のためにクレジットカードの入力を求めらるが(すくなくとも以前に実施した時は。現時点では「不要」に変わっている可能性あり)、実際に「従量制のサービスプラン」を明示的に選択して利用しない限り、課金されることはない。

本記事で扱う「アプリの登録」は無償で利用が可能。

サンプルコードの動作環境

以下の通り。

  "dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "express": "~4.16.1",
    "express-session": "^1.17.2",
    "morgan": "~1.9.1",
    "passport": "^0.5.0",
    "passport-openidconnect": "0.0.2"
  },
  "devDependencies": {
    "cross-env": "^7.0.3",
    "node-dev": "^7.1.0"
  }

各種OIDCのIdPへの登録方法について

RPとしてOIDC認証を行うには、IdPのいわゆる「openid-configuration」情報(EndPointとサポートする形式)と、RP個別に以下の登録が必要となる。

  • クライアントID
  • クライアントシークレットの
  • コールバックURI

以下の節で、IdPのそれぞれの提供元(GCP/Azure/Yahoo)ごとの情報と登録方法について説明する。

なお、いずれのIdP側の操作画面も、2021-12-05時点のものである。

GCPが提供するOIDCのIdPを利用する方法

GCP(Google)が提供するOIDC認証用のIdPの情報は、以下に記載されている。

具体的には、上記にて示されている下記を参照する。

上記を参照して、本サンプルコードでは、passport-openidconnectの提供するStrategyインスタンスのConfigureへ、次のように設定する(ClientIDやclientSecret等は環境変数経由で設定するものとして、後述する)。

var Instance4GoogleOIDC = new OpenidConnectStrategy(
    {
      issuer: "https://accounts.google.com",
      authorizationURL: "https://accounts.google.com/o/oauth2/v2/auth",
      tokenURL:         "https://oauth2.googleapis.com/token",
      userInfoURL:  "https://openidconnect.googleapis.com/v1/userinfo",
      clientID:     oidcConfig.CLIENT_ID,
      clientSecret: oidcConfig.CLIENT_SECRET,
      callbackURL:  THIS_ROUTE_PATH + '/' + oidcConfig.REDIRECT_URI_DIRECTORY,
      scope: ["profile"]  // 「openid 」はデフォルト指定されるので、明示的な指定は不要。
    }, function(){ /* 省略 */ } );

続いて、クライアントIDとクライアントシークレットの設定方法を説明する。

GCPにアクセスして、Googleアカウントでログインする。

右上の「コンソール」ボタンを押してGCPコンソールに移動する。

「ダッシュボード」が表示されるので、左ペインの「APIとサービス」を押下する。

この「APIとサービス」は「OAuth2.0認可によるAPIアクセス情報」を管理するページであるが、ここでOIDCのアクセス管理(受け入れるクライアントIDの作成/登録)もできる。

ここは「プロジェクト」単位での管理となるため、初回だと「新規プロジェクトの作成」画面が表示される。任意のプロジェクト名を入力して「作成」する。場所は、今回は試行なので「組織なし」のままでよい(「変更できない~」と書かれているのは、プロジェクトのObject IDのことで、プロジェクト名称、の事ではないことに注意)。

gcp_01create_project.png

「作成」を押すとダッシュボードのページへ移動して、作成完了となる。

なお、OIDCのIdP機能を利用するだけなので「APIとサービスの有効化」は不要。

続いて、「OAuth同意画面」へ移動する。
右上のドロップダウンアイコンか、もしくは左上のハンバーガーメニューから「APIとサービス>OAuth同意画面」へ移動する。

「OAuth同意画面」の作成に必要な情報を入力する(もちろん後でからも編集可能)。

gcp_05cofirm4oauth_1type.png

  • User Type
    • 本試行では「Googleアカウントを持っている人」を対象とするので「外部」を選択する
    • 下部の「作成」ボタンを押下すると「アプリ情報」のページに進む
  • アプリ情報
    • OIDCで利用者に対して「こういうアプリから、認証を求められています」と表示する情報
    • アプリ名とユーザーサポートメール、ディベロッパーの連絡先情報、の入力が必須
    • 承認済みドメイン、は後から「認証情報」のところで設定するので、ここでは【入力不要】
    • 入力を終えたら「保存して次へ」進む
  • スコープ
    • 「APIとサービス」を利用せず、認証機能のみを利用なので、デフォルトのままで「保存して次へ」進む
  • テストユーザー
    • 「スクープ」と同様に、今回は使用しないのデフォルトのままで「保存して次へ」進む

最後に(今まで入力した内容の確認として)「概要」が表示されたら、一番下までスクロールして「プロジェクトに戻る」ボタンを押せば「OAuth同意画面」の作成は完了。

gcp_10cofirm4oauth_overview_under_retrune_project.png

続いて「認証情報」から、OIDCするRP向けの「クライアントID」と「クライアントシークレット」を作成する。
なお「認証情報」を作成するには、あらかじめ「OAuth同意画面」を作成して置く必要があり、未作成の場合は下図のように「OAuth同意画面を構成してください」と求められる(ので先ほど作成した)。

gcp_11create_authinfo_with_cofirm4oauth.png

左ペインの「認証情報」、そのメニューが無い場合は左上のハンバーガーメニューから「APIとサービス>認証情報」をクリックして移動する。
作成するのは「OAuth 2.0 クライアント ID」で、上部の「認証情報を作成」をクリックしてドロップダウンするメニューから「OAuth 2.0 クライアント IDの作成」を選択する。

OAuthクライアントIDを割り当てるアプリケーションの種類を聞かれるので、本サンプルの場合は「ウェブ アプリケーション」を選択する。

gcp_13create_authinfo_type.png

すると、「承認済みのリダイレクトURI」を入力できるようになるので「+URIを追加」を押して、OIDCでのIdPからRPへのcallback先のURLを入力する。本サンプルでは、具体的には以下を入力する。複数指定できるので、クラウド上に公開するときは、そちらのcallback先URLも追加すること(※IdPへのリダイレクト時に「xxにcallbackして」とURLクエリーで指定するわけだが、それを「信用してよいか?(承認してよいか?)」をここで設定している)。

http://localhost:3000/auth-gcp/callback

gcp_15create_authinfo_callback_sample.png

「名前」はRPクライアントを識別するためのものなので、任意に入力する。
入力を終えたら、一番下の「作成」ボタンを押すと、「クライアントID」と「クライアントシークレット」が払い出されるので、これをメモする。
「クライアントシークレット」はここでしか参照できないので【忘れずにメモ】すること。

gcp_16create_authinfo_clientid_ready.png

※「クライアントID」の参照と「承認済みのリダイレクトURI」の追加は、後からもできる。「APIとサービス>認証情報>OAuth2.0クライアントID」の欄から編集アイコンをクリックして操作が可能。

以上で、IdPへの「クライアントID」と「クライアントシークレット」、そして「コールバックURL」の登録(作成)が終わったので、これをRPに設定する。
本サンプルでは環境変数を経由して設定するので、例えば、以下のようにしてサンプルコードを起動すればよい。

SET GCP_CLIENT_ID=【作成したクライアントID】
SET GCP_CLIENT_SECRET=【作成したクライアントシークレット】

npm run dev

Azureが提供するOIDC IdPを利用する方法

Azure(Microsoft)が提供するOIDC認証を行うIdPの情報は、以下に記載されている。

具体的には、上記に記載の手順に従ってAzureポータルにログインした先から辿れる下記を参照。

※なお、上述の「クイックスタート」の先にある以下の「Node.js Webアプリのチュートリアル」では、Azure提供の認証ライブラリ「Microsoft Authentication Library for Node (msal-node)」を利用しているが、本記事では「他のOIDCのIdPと共通の実装から利用する」ことを目的とするので、こちらではなく、冒頭に記載した「Passport-OpenID Connect」を用いる。

上述のIdPの情報( openid-configuration )参照して、本サンプルコードでは、passport-openidconnectの提供するStrategyインスタンスのConfigureへ、次ように設定する(ClientIDやclientSecret等は環境変数経由で設定するものとして、後述する)。

var Instance4AzureOIDC = new OpenidConnectStrategy(
    {
      issuer: "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0",
      authorizationURL: "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize",
      tokenURL:         "https://login.microsoftonline.com/consumers/oauth2/v2.0/token",
      userInfoURL:  "https://graph.microsoft.com/oidc/userinfo",
      clientID:     oidcConfig.CLIENT_ID,
      clientSecret: oidcConfig.CLIENT_SECRET,
      callbackURL:  THIS_ROUTE_PATH + '/' + oidcConfig.REDIRECT_URI_DIRECTORY,
      scope: ["profile"]  // 「openid 」はデフォルト指定されるので、明示的な指定は不要。
    }, function(){ /* 省略 */ } );

続いて、クライアントIDとクライアントシークレットの設定方法を説明する。

Azureポータルにアクセスして、Microsoftアカウントでログインする。

「ホーム」画面が表示されるので、「アプリの登録」を押下する。

「アプリの登録」が表示されていない場合は、上部バーの検索ボックスに「登録」と入力すると候補として表示されるので、それを選択する。

azure_02search_regist.png

「アプリの登録」画面で、OIDCログインを行うアプリケーション向けのクライアントIDとクライアントシークレットを作成する。そのためにはタイトル直下のメニューにある「新規登録」ボタンを押下する。

※「2020年6月30日以降~」と表示されている注意喚起は、OIDC他を利用するクライアント側でAzureが提供する「Azreu Active Directory 認証ライブラリ(ADAL)」を利用している場合向けの内容なので、今回は関係ない(利用していない)。

azure_03app_regist_dashboard.png

「アプリケーションの登録」画面が表示されるので、必要な情報を入力し、下部にある「登録」ボタンを押す

  • 名前
    • OIDCで利用者に対して「こういうアプリから、認証を求められています」と表示する際のアプリケーション名称。任意のアプリケーション名称を入力する(後で変更可能)。
  • サポートされているアカウントの種類
    • 本試行では「(個人で)Microsoftアカウントを持っている人」を対象とするので「個人用Microsoftアカウントのみ」を選択
  • リダイレクトURI(省略可能)
    • 後から「プラットフォームの追加」のところで設定するので、ここでは【入力不要】

azure_04app_scope.png

認証を行うアプリケーションの登録(作成)が完了すると、「概要」表示の画面に移動する。

※この「概要」画面は、後から参照する際は「アプリの登録」画面で「所有しているアプリケーション」の一覧から辿ることができる。

この「概要」画面に表示されている「アプリケーション(クライアント)ID」が、OIDCの「クライアントID」となる。
値の右側のアイコンをクリックするとクリップボードにコピーできるので、メモしておく(後でも、この画面で参照は可能)。

azure_06app_created4auth.png

「概要」画面の右ペインの上部にある「エンドポイント」をクリックすると、OIDCのIdPの情報が表示される。

※表示されたIdPの情報ページの「OpenID Connect メタデータ ドキュメント」に記載されているURLが、先ほど「Azureポータルにログインした先から辿れる」と書いた部分のこと。

続いて、クライアントシークレットを作成する。
左ペインの「管理>証明書とシークレット」をクリックして、作成画面に移動し、「新しいクライアント シークレット」ボタンを押下する。

「クライアント シークレットの追加」タブが開くので、以下の値を入力して「追加」ボタンを押下する。

  • 説明
    • 区別用の説明として任意に入力する
  • 有効期限
    • 任意の値を選択する

クライアントシークレットが作成される。
「値」の列に表示の値がOIDCの「クライアントシークレット」となるので、これをメモする(※「シークレットID」の列ではないので注意)。
「クライアントシークレット」はここでしか参照できないので【忘れずにメモ】すること。
(他の画面へ遷移後に、再び「証明書とシークレット」に戻ってきても「***」となっていて参照できない)

azure_11app_client_secret_created.png

最後に、OIDCのIdPから情報を受け取るRPのcallback先URLを設定する(※IdPへのリダイレクト時に「xxにcallbackして」とURLクエリーで指定するが、以下略)。
本サンプルでは、具体的には以下を入力する。複数指定できるので、クラウド上に公開するときは、そちらのcallback先URLも追加すること

http://localhost:3000/auth-azure/callback

左ペインから「管理>認証」を選択し、「プラットフォーム構成」に移動する。

「プラットフォームを追加」を押下し、「Web」を選択する。

azure_13app_auth_type.png

リダイレクトURI入力欄が表示されるので、先の値を入力し、下部の「構成」ボタンを押下する。

※今回は「認可コードフロー」なので、下部にあるチェックボックスはチェックしない(これらは、暗黙的なフロー、ハイブリッドフロー用)

※中段にある「ログアウト用のURL」も、今回は試行なのでSkipする。

azure_15app_auth_web_callback_sample.png

リダイレクトURIの設定が完了すると、以下の表示される。
この設定内容は、後から同様に左ペインの「管理>認証」から辿ることで参照や編集が可能。

azure_17app_auth_web_callback_finished.png

以上で、IdPへの「クライアントID」と「クライアントシークレット」、そして「コールバックURL」の登録(作成)が終わったので、これをRPに設定する。
本サンプルでは環境変数を経由して設定するので、例えば、以下のようにしてサンプルコードを起動すればよい。

SET AZURE_CLIENT_ID=【作成したクライアントID】
SET AZURE_CLIENT_SECRET=【作成したクライアントシークレット】

npm run dev

Yahooが提供するOIDC IdPを利用する方法

Yahooが提供するOIDC認証を行うIdPの情報は、以下に記載されている。

具体的には、上記のページ内にリンクのある『Authorization Codeフロー』の先で案内されている以下を参照する。

上記のIdPの情報( openid-configuration )参照して、本サンプルコードでは、passport-openidconnectの提供するStrategyインスタンスのConfigureへ、次のように設定する(ClientIDやclientSecret等は環境変数経由で設定するものとして、後述する)。

var Instance4YahooOIDC = new OpenidConnectStrategy(
    {
      issuer: "https://auth.login.yahoo.co.jp/yconnect/v2",
      authorizationURL: "https://auth.login.yahoo.co.jp/yconnect/v2/authorization",
      tokenURL:         "https://auth.login.yahoo.co.jp/yconnect/v2/token",
      userInfoURL:  "https://userinfo.yahooapis.jp/yconnect/v2/attribute",
      clientID:     oidcConfig.CLIENT_ID,
      clientSecret: oidcConfig.CLIENT_SECRET,
      callbackURL:  THIS_ROUTE_PATH + '/' + oidcConfig.REDIRECT_URI_DIRECTORY,
      scope: ["profile"]  // 「openid 」はデフォルト指定されるので、明示的な指定は不要。
    }, function(){ /* 省略 */ } );

続いて、クライアントIDとクライアントシークレットの設定方法を説明する。

「Yahooデベロッパーネットワークトップ > アプリケーションの管理」へアクセスしして、Yahooアカウントでログインする。
具体的には下記のURLにアクセスしてログインする。これは上述のページ内の「ClientIDを登録しましょう」のリンク先が該当する。

「アプリケーションの管理」画面が表示されるので「新しいアプリケーションを開発」ボタンを押下する。
(既に作成済みのものは「アプリケーション一覧」に表示され、ここから編集画面へ移動が可能)

「新しいアプリケーションを開発」の画面が表示されるので以下の情報を入力し、
下部にある「確認」ボタンを押下する。

  • アプリケーションの種類
    • 「サーバーサイド(Yahoo! ID連携 v2)」を選択
  • アプリケーション利用者情報
    • 利用者情報
    • 個人としての試行なので「個人」を選択する
    • メールアドレス
    • (変更不要)
  • アプリケーションの基本情報
    • アプリケーション名
    • OIDCで利用者に対して「こういうアプリから、認証を求められています」と表示する際のアプリケーション名称。任意のアプリケーション名称を入力する(後で変更可能)。
    • サイトURL
    • とりあえず何か入れる。※リダイレクトURI*ではない*ので注意。
    • デフォルトの「http://example.com/」のままでもよい。
    • アプリケーションの説明
    • 任意なので入力省略(あとで変更可能)
    • 利用するスコープ
    • (変更不要であり、そもそも変更できない)
    • 「利用可能なスコープはありません」と記載されているが、「ここで明示的に追加可能なスコープはありません」の意図なので問題ない
  • ガイドラインを確認する
    • ガイドラインに同意しますか?
    • 「ガイドライン」のリンク先を確認後、問題なければ「同意する」を選択
    • (当然ながら、同意できない場合は、利用できない)

yahoo_02app_create.png

「入力内容の確認」ページが表示されるので、先のページで入力した内容に誤りがないことを確認し、「登録」ボタンを押下する。

「登録完了」の画面にて、
「登録が完了し、Client IDおよびシークレットが発行されました」
と表示されるので、このクライアントIDとクライアントシークレットの値をメモする。

なお、Yahooの場合は、クライアントシークレットの値も(GCPやAzureとは異なり)、「アプリケーションの管理>アプリケーション一覧>編集」と辿ることで後から参照可能。

yahoo_04app_clientid_and_secret-2short.png

最後に、OIDCのIdPから情報を受け取るRPのcallback先URLを設定する(※IdPへのリダイレクト時に「xxにcallbackして」とURLクエリーで指定するが、以下略)。
本サンプルでは、具体的には以下を入力する。複数指定できるので、クラウド上に公開するときは、そちらのcallback先URLも追加すること

http://localhost:3000/auth-yahoo/callback

「登録完了」の画面で「アプリケーションの詳細」を押下するか、
「アプリケーションの管理>アプリケーション一覧」にて対象のアプリケーションの「編集」ボタンを押下することで、callback先URLの編集画面に移動する。

「アプリケーションの詳細」画面の下段に「コールバックURL」を入力する欄があるので、ここを上記の値に書き換えて、「更新」ボタンを押下する。

yahoo_06app_callback_url.png

以上で、IdPへの「クライアントID」と「クライアントシークレット」、そして「コールバックURL」の登録(作成)が終わったので、これをRPに設定する。
本サンプルでは環境変数を経由して設定するので、例えば、以下のようにしてサンプルコードを起動すればよい。

SET YAHOO_CLIENT_ID=【作成したクライアントID】
SET YAHOO_CLIENT_SECRET=【作成したクライアントシークレット】

npm run dev

以上ー。

蛇足/その他

返却されるprofileの違いについて

トークンEndPointが返却するIDトークンは、OIDCの規格で定められているが、UserInfoエンドポイントが返却するprofileの内容はIdP毎に自由度がある。

実際、GCPとAzureではprofileに「displayName」フィールドが含まれるが、Yahooの場合は「displayName」フィールドが無い、と言うように差があるので、注意すること。(なお、Yahooにもnameフィールドはオブジェクトとして存在した。私の環境では値は空だったが)。

参考サイト

以下、いずれも本文中に記載済みであるが、今回に試行したOIDCのIdPを提供してくれているサービスの公式案内ページと、IdPの「openid-configuration」とを記載する。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1