OpenID Connect による認証

最終更新日: 2021年7月16日
R8 | R9

概要

OpenID Connect (OIDC) は認証に関するオープンな規格の一つです。Google, LINE, Microsoft (Azure, ADFS), Oracle(Oracle Identity Cloud Service), PayPal, リクルートID, RedHat(keycloak), Salesforce, VMware, Yahoo! Japan など多くのサービスで利用できます。

OIDC の認可コードフローを示します。Wagbyは "Relying Party" という役割になります。"OpenID Provider" にはさまざまなベンダーがあります。ここでは Google を例にしています。

図1 OIDC認可コードフロー

OIDC を利用すると、Wagbyのログオン画面は使われなくなります。代わって、Googleの認証画面が表示されます。

図2 Googleへのログインを行う

ログオンに成功すると、Wagbyのメニュー画面に遷移します。

図3 ログオン後はメニュー画面へ遷移する

WagbyとのID連携に失敗する(アカウントが存在しない等)とエラー画面に遷移します。

図4 ログオンエラー

準備するもの

OIDC を利用するにあたって、次の情報を事前に取得しておきます。

OpenID Connect Provider(OP)で用意するもの

  • クライアントID(client-id)
  • クライアントシークレット(client-secret)
  • 各エンドポイントのURL(認可、トークン、UserInfo)

Relying Party(Wagby)で用意するもの

  • フローの種類
    • Webアプリの場合は "認可コードフロー" となる。
  • フローの実装コード
    • Wagbyには "Spring Security" が同梱されているので、このままでよい。
  • ログイン後(認可コードレスポンス時)にOPからリダイレクトするURL
    • Spring Security利用時は次のようになる。赤字は可変部分。
      http://localhost:8921/wagby/login/oauth2/code/google
      

Wagby が同梱している Spring Security は OpenID Connect に対応しています。そのため Relaying Party として用意すべきものはほぼ、揃っています。

一方で、OpenID Connect Provider から取得すべき情報は、利用するサービスごとに異なります。ここで取得した情報を Spring Security のパラメータとして図5の欄に記載します。

図5 OIDCに関する設定を記載する欄

Googleを利用する

OpenID Connect Provider(OP) として Google を利用した例を説明します。次の情報を取得します。

  • クライアントID(client-id)
  • クライアントシークレット(client-secret)
  • 各エンドポイントのURL(認可、トークン、UserInfo)

ただしエンドポイントURLはすでに定められています。次の通りです。

エンドポイント種別 URL
認可エンドポイントhttps://accounts.google.com/o/oauth2/v2/auth
トークンエンドポイントhttps://www.googleapis.com/oauth2/v4/token
UserInfoエンドポイントhttps://www.googleapis.com/oauth2/v3/userinfo
JWK Setエンドポイントhttps://www.googleapis.com/oauth2/v3/certs

Spring Security を利用する場合、上記の情報は標準値となっているため、省略できます。そのため実際には「クライアントID」と「クライアントシークレット」だけを取得する必要があります。

Google Developers Console

クライアントIDとクライアントシークレットを取得するため、Google Developers Console を使います。ここではすでに Google のアカウントを持っていることを前提にしています。また Google Developers Console の詳細は割愛します。

はじめに、新規プロジェクトを作成します。

図6 新しいプロジェクトの作成(1)

ここではプロジェクト名を "demo001" としています。また、場所は "組織なし" としています。

続く説明は、適切なプロジェクト名に置換してお読みください。
図7 新しいプロジェクトの作成(2)

OAuth 同意画面とは、図2にある(Googleが用意した)画面をいいます。まず入力したプロジェクト名 "demo001" となっていることを確認します。問題なければ "User Type" を指定します。

図8 OAuth同意画面を用意する(1)

「アプリケーション名」と「サポートメール」を指定します。ここではアプリケーション名として "Wagby OIDCデモアプリ" としています。サポートメールは Google から送られてくる管理用メールの受け取り先を指定します。

図9 OAuth同意画面を用意する(2)

「認証情報」を指定します。"OAuthクライアントID" とします。

図10 認証情報の設定

OAuthクライアントIDを作成します。「アプリケーションの種類」を "ウェブアプリケーション" とします。「名前」は任意です。ここでは "ウェブクライアント1" としています。「承認済みのリダイレクトURI」を "http://localhost:8921/wagby/login/oauth2/code/google" としています。

ローカルでの動作検証時は URI に localhost:8921 と指定することができます。本番環境では http://localhost:8921/wagby の部分は適切な値に変更してください。
図11 OAuthクライアントIDの作成

OAuthクライアントIDを作成すると、クライアントIDとクライアントシークレットが取得できるようになります。図のようにポップアップダイアログに表示されますので、コピーしておいてください。

図12 クライアントIDとクライアントシークレットが表示される

Wagbyの設定

認証方式

"環境 > サーバ > 認証 > 認証方式" を設定します。 認証方式に "外部認証(HttpServletRequest#getRemoteUser()を利用)" を指定します。

この設定を有効にすると、標準で同梱されているアカウント(juser)による認証は行われなくなり、request.getRemoteUser() から取得したユーザー名でWagbyのログオン処理が行われるようになります。この時、パスワードは不要です。

図13 外部認証の指定

OpenID Connect

"環境 > サーバ > 認証 > OpenID Connect" を設定します。この設定欄に記述した内容は、Spring Security が利用するプロパティファイル application.properties に反映されます。

図14 OpenIDConnectの設定(Google用)

仕様上は、以下の設定が必要になります。

spring.security.oauth2.client.registration.google.client-id=${クライアントID}
spring.security.oauth2.client.registration.google.client-secret=${クライアントシークレット}
spring.security.oauth2.client.registration.google.provider=google
spring.security.oauth2.client.registration.google.scope=openid,profile,email
spring.security.oauth2.client.registration.google.redirect-uri-template={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.google.client-authentication-method=basic
spring.security.oauth2.client.registration.google.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.google.authorization-uri=https://accounts.google.com/o/oauth2/v2/auth
spring.security.oauth2.client.provider.google.token-uri=https://www.googleapis.com/oauth2/v4/token
spring.security.oauth2.client.provider.google.user-info-uri=https://www.googleapis.com/oauth2/v3/userinfo
spring.security.oauth2.client.provider.google.jwk-set-uri=https://www.googleapis.com/oauth2/v3/certs
spring.security.oauth2.client.provider.google.user-name-attribute=email

ところが Spring Security には google に関する設定が最初から組み込まれています。そこでクライアントIDとクライアントシークレット以外は省略可能となっています。よって開発者が設定するのは次の二行です。

spring.security.oauth2.client.registration.google.client-id=${クライアントID}
spring.security.oauth2.client.registration.google.client-secret=${クライアントシークレット}

重要

[重要] クライアントID、クライアントシークレットの扱い

ここまで、Designerに設定する方法を説明しましたが、Wagbyのリポジトリはテキスト情報であるため、仮にリポジトリが外部に渡されると、これらの情報を読み取ることができます。セキュリティ上、問題となる懸念があります。

この対策として、実際にはリポジトリには記述せず、ビルド後のアプリケーションに含まれる WEB-INF/classes/application.properties に直接クライアントID、クライアントシークレットを指定すると安全性を高めることができます。

テストアカウントを用意する

認証方式に "外部認証(HttpServletRequest#getRemoteUser()を利用)" を指定したため、認証されたアカウント(Wagbyのユーザー)が juser に存在しない場合はログオンできません。このため、OP で認証が通っても Wagby 側に該当ユーザーが存在しない場合はログオン失敗となります。(図4)

内蔵DBを利用している場合は、次のようなカスタマイズファイルを作成しておくとビルドの DB 初期化時に自動的にアカウントがインポートされます。この例では「システム管理者権限」を付与しています。

外部DB利用時は、以下の内容に沿ったテストアカウントを事前にjuserテーブルに用意してください。

customize/webapp/WEB-INF/export/init/juser/item_1000.xml

<?xml version="1.0" encoding="UTF-8"?>
  <juser>
  <userid>taro@gmail.com</userid>
  <passwd>dummy</passwd>
  <name>ジャスミン太郎</name>
  <level>0</level>
  <jprincipalId>3</jprincipalId>
</juser>
useridの値は、実際に Google に用意された、存在するアカウントである必要があります。
passwdの値は何でもかまいません。この値は利用されません。
jprincipalId "3" は、システム管理者権限を指します。

同期は手動

Wagbyのアカウント(juser)と、OPのアカウントの同期は自動的には行われません。同期の方法は別途、検討する必要があります。詳細はWagby販売代理店へご相談ください。

ユーザ識別子

実は Google では、一人の利用者が複数のメールアドレスを保有することができます。そのため、OP に Google を利用したとき、認証後に渡されるアカウントの情報は、その人を特定する ID として、数字の羅列が返される仕様となっています。これが「ユーザ識別子」です。

しかしこの仕様どおりとすると、Wagby側に用意するアカウントも "taro@gmail.com" ではなく、"123456789..." のような数字が並んだものとなります。これはわかりにくいため、WagbyではOPから返される値のうち、メールアドレスを使うようにしています。これは次の設定となっています。

spring.security.oauth2.client.provider.google.user-name-attribute=email

この設定が含まれているため、Googleログイン時に用いたメールアドレスと同じものをWagbyアカウントとして用意することで連携できるようにしています。

ユーザ識別子をカスタマイズする

OPから受け取ったユーザ識別子をカスタマイズし、それをWagbyアカウントとして利用することもできます。[詳細...]

Azure Active Directory を利用する

OpenID Connect Provider(OP) として Azure Active Directory (AAD) を利用した例を説明します。次の情報を取得します。

  • クライアントID(client-id)
  • クライアントシークレット(client-secret)
  • テナントID
  • グループ名
  • 各エンドポイントのURL(認可、トークン、UserInfo)

ただし各エンドポイントのURLは省略できます。Wagby には Microsoft が提供している AAD 接続設定用クラスが同梱されているためです。

AADはテナントごとに独立しているため、${テナントID} を指定します。これによって AAD が一意に特定されます。

${グループ名}には連携対象のユーザが所属するグループ名を指定します。

クライアントIDとテナントIDの取得

以下のページの "AD テナントへのアプリケーションの登録" を参考にしてください。 これは Azure Active Directory は構築済みという前提で、Open ID Connect 接続のための設定を行う手順となっています。

https://docs.microsoft.com/ja-jp/azure/active-directory/develop/quickstart-register-app#register-a-new-application-using-the-azure-portal

ローカルホストでの動作確認の場合は、"リダイレクト URI" 次のようになります。赤字は可変部分です。

http://localhost:8921/wagby/login/oauth2/code/azure
ローカルでの動作検証時は URI に localhost:8921 と指定することができます。本番環境では http://localhost:8921/wagby の部分は適切な値に変更してください。

設定後に "アプリケーション (クライアント) ID" と "ディレクトリ (テナント) ID" が 表示されます。これをメモしておいてください。

クライアントシークレットの取得

以下のページの "資格情報を Web アプリケーションに追加する" を参考に "新しいクライアント シークレット" の追加を行います。なお、手順2の「証明書の追加」は今回は不要です。

https://docs.microsoft.com/ja-jp/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application

この対応で "クライアント シークレット" の値が表示されます。これをメモしておいてください。

マニフェストの変更とグループ名の取得

以下のページを参考にマニフェストを編集します。

https://docs.microsoft.com/ja-jp/azure/active-directory/develop/quickstart-configure-app-expose-web-apis#expose-a-new-scope-or-role-through-the-application-manifest

具体的には2つの設定値を false から true に変更して保存します。

"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,

最後に、認証に用いるグループを確認します。
https://portal.azure.com/ の "Azure サービス > Azure Active Directory > グループ" で表示されるグループ名をメモしておいてください。

Wagbyの設定

認証方式

"環境 > サーバ > 認証 > 認証方式" を設定します。 認証方式に "外部認証(HttpServletRequest#getRemoteUser()を利用)" を指定します。

この設定を有効にすると、標準で同梱されているアカウント(juser)による認証は行われなくなり、request.getRemoteUser() から取得したユーザー名でWagbyのログオン処理が行われるようになります。この時、パスワードは不要です。

図15 外部認証の指定

OpenID Connect

"環境 > サーバ > 認証 > OpenID Connect" を設定します。この設定欄に記述した内容は、Spring Security が利用するプロパティファイル application.properties に反映されます。

これまでにメモした "クライアント ID" と "クライアント シークレット"、"テナントID"、"グループ名" を customize/resources/myapplication.properties に次のように記述します。

spring.security.oauth2.client.registration.azure.client-id=${クライアント ID}
spring.security.oauth2.client.registration.azure.client-secret=${クライアント シークレット}
azure.activedirectory.tenant-id=${テナントID}
azure.activedirectory.active-directory-groups=${グループ名}

グループ名が複数ある場合は "," で区切って記述します。

重要

[重要] クライアントID、クライアントシークレットの扱い

ここまで、Designerに設定する方法を説明しましたが、Wagbyのリポジトリはテキスト情報であるため、仮にリポジトリが外部に渡されると、これらの情報を読み取ることができます。セキュリティ上、問題となる懸念があります。

この対策として、実際にはリポジトリには記述せず、ビルド後のアプリケーションに含まれる WEB-INF/classes/application.properties に直接クライアントID、クライアントシークレットを指定すると安全性を高めることができます。

テストアカウントを用意する

Wagby 側では事前に AAD 認証に用いるアカウントと同じユーザーIDを持つアカウントを作成しておく必要があります。詳細は Google を使った場合の説明を参考にしてください。

動作確認

これらの設定後にビルドし、Wagby アプリケーションにアクセスします。Wagby のログオン画面に変わって Microsoft の認証画面が表示されるようになります。

その他のOPを利用する

Keycloakをはじめとする、ここに記載していない認証サーバでも、Spring Security が対応している製品であれば接続できることがあります。本ページに記載の内容ならびに Spring Security の情報をガイドにお試しください。

二段階認証・多要素認証

これまで説明したように OpenID Connect は認証処理を他のサービスへ移譲する機能です。

そのため OpenID Connect を使って他のサービスへ認証処理を移譲し、移譲された側の持つ機能として二段階認証・多要素認証を利用することができます。例を示します。

  1. OpenID Connect を使って、Google へ認証処理を移譲する。
  2. 利用者の Google アカウントの設定で2段階認証プロセス(2要素認証プロセス)を有効にする。(2段階認証プロセスでは、SMS認証や Google Authenticator を使った認証を選択可能)。

Google 以外にも OpenID Connect に対応し、かつ多要素認証にも対応したサービスがあります。Wagbyでは特に指定するものはありません。自由に選択してください。

サポートポリシー

  • OpenID Connect に関する問い合わせ(接続できない、どう設定するか、など)は Premium Support となります。認証サーバ、お客様環境、Wagbyアプリ、それぞれの環境に依存するためです。
  • サポートはお客様の「認証サービス運用担当者」とやりとりします。これは認証サーバ製品に関する知識を有することが前提です。認証サービスの運用は、お客様環境の運用ポリシー、セキュリティポリシーと関わるためです。
  • 本ページに記載の内容は、接続のための最低限の事柄を記載したものです。さらに追加設定が必要な環境もあるかも知れません。あらかじめご了承ください。