Apache HTTP Server + mod_auth_openidc で OpenID Connect (OIDC) 認証が必要な Web サイトを作ってみます。
本記事は「1. 準備編」の続き「2. d アカウント・コネクト編」です。準備編の設定が終わっている状態からはじめて、d アカウント・コネクトでソーシャルログインできるようにしてみます。次の記事は d アカウント・コネクトではなくて Google アカウントでソーシャルログインできるようにしてみる「3. Google アカウント編」です。さらにその次にはログイン時に d アカウント・コネクトか Google アカウントかを選択できるようにする「4. マルチプロバイダ編」を予定しています。
もしかしたらマズい設定などがあるかもしれません。気が付いた方はご指摘いただけるとありがたいです。
d アカウント・コネクト
d アカウントでソーシャルログインできるサービスです。OpenID Connect に対応しているので mod_auth_openidc で使えるハズです。ログイン機能のみであればオンラインでの申し込みが可能かつ無料で利用でき、メールアドレスやその他のユーザ情報が欲しければ別途審査が必要だったり有償になったりするようです(2022年6月現在)。
設定
今回は、無償・オンライン申し込みで利用できるタイプのものを使います。申し込み方法などは本記事では説明しませんのでご自分でお調べください。申請が通ると技術情報としてマニュアルやライブラリなどがダウンロードできるようになるようですが、諸事情によりそれらは一切参照せず利用せずに設定していきます。
払い出してもらう設定と、こちらから設定する項目とその内容は以下の通りです。
- 払い出してもらう設定
- クライアント ID(文字列)
- クライアントシークレット(文字列、秘密にしておく必要がある)
- 設定する項目と設定内容
- リダイレクト URI :
https://example.com/oidc/redirect_uri
- OIDC 認証を要する URL が https://example.com/oidc/ 以下になるように設定することにして、その中のコンテンツを置かない適当な URL を指定します
- 利用可能スコープ:
openid
- https://github.com/auth0/passport-daccount/blob/v0.1.0/lib/strategy.js#L48 の設定値を参考に OIDC 規格で必要最低限なスコープ openid だけにしておきます
- リダイレクト URI :
mod_auth_openidc
OIDC 認証をしてくれるモジュールです。
インストール
Ubuntu 20.04 にはパッケージがあるので、それをインストールします。
$ sudo apt install libapache2-mod-auth-openidc
これで mod_auth_openidc ver. 2.4.1 がインストールされました。
設定
mod_auth_openidc の設定をしていきます。デフォルトの設定ファイルが /etc/apache2/mods-available/auth_openidc.conf
にあるので、これを auth_openidc.conf.org
にバックアップしておき、以下のように設定を書き換えていきます。
OIDCRedirectURI
リダイレクト URI を指定します。d アカウント・コネクトへ設定した内容と同じものにします。
OIDCRedirectURI https://example.com/oidc/redirect_uri
OIDCCryptoPassphrase
mod_auth_openidc が内部で使用する暗号化のパスフレーズを設定します。何かランダムな文字列を生成して設定するとよいでしょう。以下の例では文字列 foobarbaz
を設定しています。
OIDCCryptoPassphrase foobarbaz
OIDCProviderIssuer
Provider の issuer identifier を設定します。 https://github.com/auth0/passport-daccount の設定値を参考に手動で ID トークンを取得したところ iss クレームに https://conf.uw.docomo.ne.jp/
が設定されていましたのでこれを設定します。
OIDCProviderIssuer https://conf.uw.docomo.ne.jp/
OIDCProviderAuthorizationEndpoint
Authorization endpoint を設定します。 https://github.com/auth0/passport-daccount/blob/v0.1.0/lib/strategy.js#L46 を元に以下の設定にします。
OIDCProviderAuthorizationEndpoint https://id.smt.docomo.ne.jp/cgi8/oidc/authorize
OIDCProviderTokenEndpoint
Token endpoint を設定します。 https://github.com/auth0/passport-daccount/blob/v0.1.0/lib/strategy.js#L47 を元に以下の設定にします。
OIDCProviderTokenEndpoint https://conf.uw.docomo.ne.jp/common/token
OIDCProviderTokenEndpointAuth
Token endpoint へアクセスするときの認証方式です。 https://github.com/auth0/passport-daccount/blob/v0.1.0/lib/strategy.js#L53 の記述内容から client_secret_basic 方式であることがわかるので、これを設定します。
OIDCProviderTokenEndpointAuth client_secret_basic
OIDCScope
スコープを設定します。d アカウント・コネクトへ設定した内容と同じものにします。
OIDCScope "openid"
OIDCResponseType
フローを設定します。 https://github.com/auth0/passport-daccount/blob/v0.1.0/test/strategy.test.js#L49 に response_type=code
とあるのでこれを設定します。
OIDCResponseType "code"
OIDCClientID
クライアント ID を設定します。d アカウント・コネクトから払い出された文字列をそのまま設定します。
OIDCClientID xxxxxxxxxxxxxxxx
OIDCClientSecret
クライアントシークレットを設定します。d アカウント・コネクトから払い出された文字列をそのまま設定します。
OIDCClientSecret XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
OIDCCookiePath
mod_auth_openidc が使用する Cookie のパスを設定します。今回は OIDC 認証を要する URL を https://example.com/oidc/ 以下にするため /oidc/
を設定します。
OIDCCookiePath /oidc/
差分
以上により設定ファイルのバックアップとの差分は以下のようになりました。
--- auth_openidc.conf.org
+++ auth_openidc.conf
@@ -10,14 +10,14 @@
# but it must NOT point to any actual content that needs to be served.
# You can use a relative URL like /protected/redirect_uri if you want to
# support multiple vhosts that belong to the same security domain in a dynamic way
-#OIDCRedirectURI https://www.example.com/protected/redirect_uri
+OIDCRedirectURI https://example.com/oidc/redirect_uri
# (Mandatory)
# Set a password for crypto purposes, this is used for:
# - encryption of the (temporary) state cookie
# - encryption of cache entries, that may include the session cookie, see: OIDCCacheEncrypt and OIDCSessionType
# Note that an encrypted cache mechanism can be shared between servers if they use the same OIDCCryptoPassphrase
-#OIDCCryptoPassphrase <passphrase>
+OIDCCryptoPassphrase foobarbaz
#
# All other entries below this are optional though some may be required in a
@@ -49,11 +49,11 @@
# OpenID Connect Provider issuer identifier (e.g. https://localhost:9031 or https://accounts.google.com)
# Used when OIDCProviderMetadataURL is not defined or the metadata obtained from that URL does not set it.
-#OIDCProviderIssuer <issuer>
+OIDCProviderIssuer https://conf.uw.docomo.ne.jp/
# OpenID Connect Provider Authorization Endpoint URL (e.g. https://localhost:9031/as/authorization.oauth2)
# Used when OIDCProviderMetadataURL is not defined or the metadata obtained from that URL does not set it.
-#OIDCProviderAuthorizationEndpoint <authorization_endpoint>
+OIDCProviderAuthorizationEndpoint https://id.smt.docomo.ne.jp/cgi8/oidc/authorize
# OpenID Connect Provider JWKS URL (e.g. https://localhost:9031/pf/JWKS)
# i.e. the URL on which the signing keys for this OP are hosted, in JWK formatting
@@ -62,14 +62,14 @@
# OpenID Connect Provider Token Endpoint URL (e.g. https://localhost:9031/as/token.oauth2)
# Used when OIDCProviderMetadataURL is not defined or the metadata obtained from that URL does not set it.
-#OIDCProviderTokenEndpoint <token_endpoint>
+OIDCProviderTokenEndpoint https://conf.uw.docomo.ne.jp/common/token
# Authentication method for the OpenID Connect Provider Token Endpoint.
# When "private_key_jwt" is used, OIDCPrivateKeyFiles and OIDCPublicKeyFiles must have been set.
# When not defined the default method from the specification is used, i.e. "client_secret_basic".
# Used when OIDCProviderMetadataURL is not defined or the metadata obtained from that URL does not set it.
# NB: this can be overridden for dynamic client registration on a per-OP basis in the .conf file using the key: token_endpoint_auth
-#OIDCProviderTokenEndpointAuth [ client_secret_basic | client_secret_post | client_secret_jwt | private_key_jwt | none ]
+OIDCProviderTokenEndpointAuth client_secret_basic
# Extra parameters that need to be passed in the POST request to the Token Endpoint.
# Parameter names and values need to be provided in URL-encoded form.
@@ -80,7 +80,7 @@
# OpenID Connect Provider UserInfo Endpoint URL (e.g. https://localhost:9031/idp/userinfo.openid)
# When not defined no claims will be resolved from such endpoint.
# Used when OIDCProviderMetadataURL is not defined or the metadata obtained from that URL does not set it.
-#OIDCProviderUserInfoEndpoint <user_info_endpoint>
+OIDCProviderUserInfoEndpoint https://conf.uw.docomo.ne.jp/common/userinfo
# OpenID OP Check Session iFrame URL, for Session Management purposes.
# When not defined, no Session Management will be applied.
@@ -113,7 +113,7 @@
# When not defined, the bare minimal scope "openid" is used.
# NB: multiple scope values must be enclosed in a single pair of double quotes
# NB: this can be overridden on a per-OP basis in the .conf file using the key: scope
-#OIDCScope "<scope(s)-separated-by-spaces-and-enclosed-in-double-quotes>"
+OIDCScope "openid"
# Extra parameters that will be sent along with the Authorization Request.
# These must be URL-query-encoded as in: "display=popup&prompt=consent" or
@@ -192,7 +192,7 @@
# The response type (or OpenID Connect Flow) used (this serves as default value for discovered OPs too)
# When not defined the "code" response type is used.
# NB: this can be overridden on a per-OP basis in the .conf file using the key: response_type
-#OIDCResponseType ["code"|"id_token"|"id_token token"|"code id_token"|"code token"|"code id_token token"]
+OIDCResponseType "code"
# The response mode used (this serves as default value for discovered OPs too)
# When not defined the default response mode for the requested flow (OIDCResponseType) is used.
@@ -201,12 +201,12 @@
# Only used for a single static provider has been configured, see below in OpenID Connect Provider.
# Client identifier used in calls to the statically configured OpenID Connect Provider.
-#OIDCClientID <client_id>
+OIDCClientID xxxxxxxxxxxxxxxx
# Only used for a single static provider has been configured, see below in OpenID Connect Provider.
# Client secret used in calls to the statically configured OpenID Connect Provider.
# (not used/required in the Implicit Client Profile, i.e. when OIDCResponseType is "id_token")
-#OIDCClientSecret <client_secret>
+OIDCClientSecret XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# Filename with the PEM-formatted client certificate used to authenticate the Client in calls to the
# token endpoint of the OAuth 2.0 Authorization server.
@@ -449,7 +449,7 @@
# Define the cookie path for the "state" and "session" cookies.
# When not defined the default is a server-wide "/".
-#OIDCCookiePath <cookie-path>
+OIDCCookiePath /oidc/
# Specify the domain for which the "state" and "session" cookies will be set.
# This must match the OIDCRedirectURI and the URL on which you host your protected
有効化
mod_auth_openidc を有効化(/etc/apache2/mods-enabled
にシンボリックリンクを作る)します。
$ sudo a2enmod auth_openidc
Apache 設定
https://example.com/oidc/ 以下で OIDC 認証が必要になるよう設定します。
http
/etc/apache2/sites-available/001-example.com.conf
の </VirtualHost>
行の前に以下の設定を追加します。これは http を https へリダイレクトする、つまり http://example.com/oidc/ 以下へのアクセスがあった場合に https://example.com/oidc/ 以下へリダイレクトする設定です。
<Location /oidc/>
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</Location>
ファイル全体は以下のようになります。
<VirtualHost *:80>
ServerName example.com
ServerAdmin webmaster@example.com
DocumentRoot /var/www/example.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Location /oidc/>
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</Location>
</VirtualHost>
https
etc/apache2/sites-available/example.com-ssl.conf
の </VirtualHost>
行の前に以下の設定を追加します。
<Location /oidc/>
AuthType openid-connect
Require valid-user
</Location>
さらに動作確認用に環境変数を見たいため SSI を使えるようにします(OIDC 認証したいだけであれば不要な設定です)。
<Location /oidc/>
AuthType openid-connect
Require valid-user
Options +Includes
DirectoryIndex index.shtml index.html
</Location>
ファイル全体は以下のようになります。
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin webmaster@example.com
DocumentRoot /var/www/example.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-test-example-com.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-test-example-com.key
SSLCertificateChainFile /etc/apache2/ssl.crt/test-intermediate-ca.pem
<Location /oidc/>
AuthType openid-connect
Require valid-user
Options +Includes
DirectoryIndex index.shtml index.html
</Location>
</VirtualHost>
</IfModule>
リダイレクト有効化
https へのリダイレクトができるように mod_rewrite を有効化(/etc/apache2/mods-enabled
にシンボリックリンクを作る)します。
$ sudo a2enmod rewrite
SSI 有効化
SSI を有効化(/etc/apache2/mods-enabled
にシンボリックリンクを作る)します。
$ sudo a2enmod include
コンテンツ
以下の OIDC 動作確認用コンテンツを /var/www/example.com/oidc/index.shtml
に置きます。
<DOCTYPE! html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>OpenID Connect ログインしました</title>
</head>
<body>
<h1>OpenID Connect ログインしました</h1>
<p>REMOTE_USER=<!--#echo var="REMOTE_USER" --></p>
</body>
</html>
トップページから OIDC 動作確認用コンテンツへのリンクを貼るため、/var/www/example.com/index.html
を以下のようにします。
<DOCTYPE! html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>example.com テストページ</title>
</head>
<body>
<h1>example.com テストページ</h1>
<p><a href="/oidc/">ログイン</a></p>
</body>
</html>
設定の確認とサービス再起動
設定が正しいか確認します。
$ sudo apache2ctl configtest
Syntax OK
として上記のように Syntax OK と出たら確認 OK ですので、
$ sudo service apache2 restart
として再起動します。
動作確認
Windows のブラウザ(Edge など)で https://example.com を開き、「ログイン」をクリックします。d アカウント・コネクトの認証画面になり、認証されたら「遷移先 URL の確認」画面が出て、遷移先 URL として https://example.com/oidc/redirect_uri
が示されます。「OK」ボタンを押すと、さきほど設置した OIDC 動作確認用コンテンツ「OpenID Connect ログインしました」画面(ログイン中画面)になります。ここでは mod_auth_openidc が環境変数 REMOTE_USER に設定した認証したユーザの識別子が表示されます。
この識別子はアカウントを一意に識別することができる文字列ではあるようですが、d アカウントの ID や設定されたメールアドレスとは全く関係ない文字列になっています。
ログアウト
mod_auth_openidc はログアウトの処理をすることもできます。あくまでも mod_auth_openidc のセッションをログアウトする処理であって OIDC のログアウトとは異なります。この機能でログアウトできるようにしてみます。
mod_auth_openidc 設定
/etc/apache2/mods-available/auth_openidc.conf
へログアウトした時に表示される URL を指定します。ここでは https://example.com/loggedout.html に設定してみます。
OIDCDefaultLoggedOutURL https://example.com/loggedout.html
コンテンツ
ログアウトした時に表示される以下のようなコンテンツを /var/www/example.com/loggedout.html
に置きます。
<DOCTYPE! html>
<html lang="ja">
<head>
<meta charset="UTF-8"/>
<title>OpenID Connect ログアウトしました</title>
</head>
<body>
<h1>OpenID Connect ログアウトしました</h1>
<p><a href="/">トップに戻る</a></p>
</body>
</html>
ログイン中の画面 /var/www/example.com/oidc/index.shtml
にログアウトのリンクを追加します。
<DOCTYPE! html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>OpenID Connect ログインしました</title>
</head>
<body>
<h1>OpenID Connect ログインしました</h1>
<p>REMOTE_USER=<!--#echo var="REMOTE_USER" --></p>
<p><a href="/oidc/redirect_uri?session=logout">ログアウト</a></p>
</body>
</html>
設定の確認とサービス再起動
再度設定の確認とサービス再起動をします。
$ sudo apache2ctl configtest
$ sudo service apache2 restart
動作確認
ログイン中の画面から「ログアウト」のリンクをクリックするとログアウトすることができ、再度ログインしようとすると OIDC の認証が走るようになります。
設定の改良
ここまで、mod_auth_openidc のデフォルト設定ファイル /etc/apache2/mods-available/auth_openidc.conf
に設定していましたが、これだとすべての virtual host に共通の設定になってしまいます。そこで virtual host 別の設定になるようにしてみます。
デフォルト設定ファイルを元に戻す
バックアップしてあった元のファイルで上書きします。元のファイルはすべてコメント行か空行なので設定としては完全に空になります。
$ cd /etc/apache2/mods-available/
$ sudo cp auth_openidc.conf.org auth_openidc.conf
d アカウント・コネクト設定
上記 mod_auth_openidc 設定のうち、d アカウント・コネクトに特有の設定値を /etc/apache2/mods-available/auth_openidc_d_account_connect.conf
に書きます。
OIDCProviderIssuer https://conf.uw.docomo.ne.jp/
OIDCProviderAuthorizationEndpoint https://id.smt.docomo.ne.jp/cgi8/oidc/authorize
OIDCProviderTokenEndpoint https://conf.uw.docomo.ne.jp/common/token
OIDCProviderTokenEndpointAuth client_secret_basic
OIDCProviderUserInfoEndpoint https://conf.uw.docomo.ne.jp/common/userinfo
OIDCScope "openid"
OIDCResponseType "code"
クライアント ID およびクライアントシークレット
クライアント ID およびクライアントシークレットは別ファイル /etc/apache2/mods-available/auth_openidc_client_secret.conf
に書いておきます。
OIDCClientID xxxxxxxxxxxxxxxx
OIDCClientSecret XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
念のため、オーナーとパーミッションをいじって他のユーザから見えないようにします。
$ cd /etc/apache2/mods-available/
$ sudo chown www-data:www-data auth_openidc_client_secret.conf
$ sudo chmod 600 auth_openidc_client_secret.conf
サイト設定
d アカウント・コネクト設定とクライアント ID およびクライアントシークレット設定をインクルードするとともに、サイト特有の設定をするため、etc/apache2/sites-available/example.com-ssl.conf
の <Location /oidc/>
の前に以下の行を追加します(mod_auth_openidc の設定は 1 virtual host あたり 1 つだけのようで <Location /oidc/>
~ </Location>
の中に書くとエラーになってしまいました)。
Include mods-available/auth_openidc_d_account_connect.conf
Include mods-available/auth_openidc_client_secret.conf
OIDCRedirectURI https://example.com/oidc/redirect_uri
OIDCCryptoPassphrase foobarbaz
OIDCCookiePath /oidc/
OIDCDefaultLoggedOutURL https://example.com/loggedout.html
ファイル全体としては以下のようになります。
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin webmaster@example.com
DocumentRoot /var/www/example.com
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-test-example-com.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-test-example-com.key
SSLCertificateChainFile /etc/apache2/ssl.crt/test-intermediate-ca.pem
Include mods-available/auth_openidc_d_account_connect.conf
Include mods-available/auth_openidc_client_secret.conf
OIDCRedirectURI https://example.com/oidc/redirect_uri
OIDCCryptoPassphrase foobarbaz
OIDCCookiePath /oidc/
OIDCDefaultLoggedOutURL https://example.com/loggedout.html
<Location /oidc/>
AuthType openid-connect
Require valid-user
Options +Includes
DirectoryIndex index.shtml index.html
</Location>
</VirtualHost>
</IfModule>
設定の確認とサービス再起動
再度設定の確認とサービス再起動をします。
$ sudo apache2ctl configtest
$ sudo service apache2 restart
動作確認
特に問題なくログイン・ログアウトができました。
次回
本記事「2. d アカウント・コネクト編」では、d アカウント・コネクトでソーシャルログインできるようにしてみました。次の記事は d アカウント・コネクトではなくて Google アカウントでソーシャルログインできるようにしてみる「3. Google アカウント編」です。さらにその次にはログイン時に d アカウント・コネクトか Google アカウントかを選択できるようにする「4. マルチプロバイダ編」を予定しています。