mod_auth_openidc で OpenID Connect (OIDC) 認証を --- 3. Google アカウント編

Apache HTTP Server + [mod\_auth\_openidc](https://github.com/zmartzone/mod_auth_openidc) で OpenID Connect (OIDC) 認証が必要な Web サイトを作ってみます。

本記事は「[1. 準備編](https://qiita.com/trueroad/items/1bcc1870d0b03e6f5029)」「[2. d アカウント・コネクト編](https://qiita.com/trueroad/items/3562be88b1d48130c18c)」に続く「3. Google アカウント編」です。d アカウント・コネクト編の設定が終わっている状態から、d アカウント・コネクトではなく Google アカウントでソーシャルログインできるように変更してみます。次の記事は「[4. マルチプロバイダ編](https://qiita.com/trueroad/items/3d8a7dae83c7af66518b)」として d アカウント・コネクトと Google アカウントの両方でソーシャルログインできるようにします。

もしかしたらマズい設定などがあるかもしれません。気が付いた方はご指摘いただけるとありがたいです。

## Google アカウント

OpenID Connect (OIDC) に対応していてソーシャルログインに使えるものとして有名ですね。支払設定をしなくてもとりあえず使うことができました。$300 相当の無料トライアルを有効化しなければクレジットカード情報の登録も必要ありませんでした（2022 年 6 月現在）。

### 設定

今回は公開ステータス「テスト」のままで使ってみます。そのため後で登録するテストユーザしか使えません。「アプリを公開」にすると本番環境となり全ユーザが使えるようになりますが、審査が必要などいろいろあるようです。支払設定なども必要になるのかもしれませんが、やっていないのでわかりません。設定方法などは本記事では説明しませんのでご自分でお調べください。

#### プロジェクト作成

ブラウザで https://console.cloud.google.com/apis/ を開き「API とサービス」画面で適当にプロジェクトを作成します。プロジェクト名、プロジェクト ID、場所など全部デフォルトのまま作成してみました。プロジェクト名は後から変更可能、プロジェクト ID は後から変更できないようです。

#### 「OAuth 同意画面」の設定項目

「API とサービス」画面で作成したプロジェクトが選択されている状態で「OAuth 同意画面」をクリックしてアプリを登録します。ほとんどの項目は後から変更可能みたいなので適当に設定すればよさそうです。

* ユーザの種類
    + 「外部」に設定します
        - 「内部」は Google Workspace 用のものでメンバ限定などができるようです
* スコープ
    + 以下の 3 種類を設定します
      （それ以外の選択肢は選択できないし、
      新しいものを追加することもできないようです）
        - .../auth/userinfo.email: Google アカウントのメインのメールアドレスの参照
        - .../auth/userinfo.profile: ユーザーの個人情報の表示（ユーザーが一般公開しているすべての個人情報を含む）
        - openid: Google で公開されているお客様の個人情報とお客様を関連付ける
* テストユーザ
    + とりあえず自分だけ追加しておきます
        - 100 アカウントまで追加可能のようです

#### 「認証情報」の設定項目

次に「API とサービス」画面で「認証情報」をクリックします。「＋認証情報を作成」をクリックして「OAuth クライアント ID」を選びます。

* アプリケーションの種類
    + 選択肢はいろいろあるようですが mod\_auth\_openidc で使うなら「ウェブアプリケーション」にします
* 名前
    + 適当にデフォルトのままにしてみました
* 承認済みの JavaScript 生成元
    + 何も入れません
* 承認済のリダイレクト URI（d アカウント・コネクト編と同じ設定にします）
    + `https://example.com/oidc/redirect_uri`

「作成」するとクライアント ID とクライアントシークレットが表示され、それらが入った json をダウンロードできるようになりますので、ダウンロードしておきます。

## mod\_auth\_openidc

d アカウント・コネクト編で作った `/etc/apache2/mods-available/auth_openidc_d_account_connect.conf` と同様の設定ファイルを `/etc/apache2/mods-available/auth_openidc_google_account.conf` に作ります。同様にクライアント ID およびクライアントシークレットも `/etc/apache2/mods-available/auth_openidc_client_secret_google.conf` に置いておきます。

### 設定

`/etc/apache2/mods-available/auth_openidc_google_account.conf` の設定です。

#### OIDCProviderMetadataURL

Google Account は OpenID Connect Discovery に対応しているので、その URL を設定します。これで多くの設定項目が自動的に取得できるため、いちいち設定ファイルに書かなくて済むようになります。

```
OIDCProviderMetadataURL https://accounts.google.com/.well-known/openid-configuration
```

#### OIDCScope

スコープを設定します。「OAuth 同意画面」で 3 つ設定したので、それに対応する 3 種類を書いておきます。

```
OIDCScope "openid email profile"
```

#### OIDCResponseType

フローを設定します。「認証情報」で「ウェブアプリケーション」と設定したので、それに対応する設定にします。

```
OIDCResponseType "code"
```

#### 設定ファイル

以上により設定ファイル `/etc/apache2/mods-available/auth_openidc_google_account.conf` の全体は以下のようになります。

```auth_openidc_google_account.conf
OIDCProviderMetadataURL https://accounts.google.com/.well-known/openid-configuration
OIDCScope "openid email profile"
OIDCResponseType "code"
```

### クライアント ID およびクライアントシークレット

クライアント ID およびクライアントシークレットは別ファイル `/etc/apache2/mods-available/auth_openidc_client_secret_google.conf` に書いておきます。

```auth_openidc_client_secret_google.conf
OIDCClientID xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
OIDCClientSecret XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

念のため、オーナーとパーミッションをいじって他のユーザから見えないようにします。

```
$ cd /etc/apache2/mods-available/
$ sudo chown www-data:www-data auth_openidc_client_secret_google.conf
$ sudo chmod 600 auth_openidc_client_secret_google.conf
```

## Apache サイト設定

`/etc/apache2/sites-available/example.com-ssl.conf` でインクルードしている mod\_auth\_openidc の設定ファイルを先ほど作成した設定ファイルへ変更します。

```
		Include mods-available/auth_openidc_d_account_connect.conf
		Include mods-available/auth_openidc_client_secret.conf
```

を

```
		Include mods-available/auth_openidc_google_account.conf
		Include mods-available/auth_openidc_client_secret_google.conf
```

に変更します。ファイル全体としては以下のようになります。

```example.com-ssl.conf
<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_google_account.conf
		Include mods-available/auth_openidc_client_secret_google.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
Syntax OK
```

として上記のように Syntax OK と出たら確認 OK ですので、

```
$ sudo service apache2 restart
```

として再起動します。

## 動作確認

Windows のブラウザ（Edge など）で https://example.com を開き、「ログイン」をクリックします。Google アカウントの認証画面になり、認証されたら OIDC 動作確認用コンテンツ「OpenID Connect ログインしました」画面（ログイン中画面）になります。ここでは mod\_auth\_openidc が環境変数 REMOTE_USER に設定した認証したユーザの識別子が表示されます。

この識別子はアカウントを一意に識別することができる文字列ではあるようですが、Google アカウントの ID やメールアドレスとは全く関係ない文字列になっています。

## スコープ

d アカウント・コネクト編と異なり、スコープに openid だけではなく email と profile も設定しましたので、こちらの情報も得られているハズです。そこで、OIDC 動作確認用コンテンツを少し書き換えてこれらの情報も表示できるようにしてみます。

### コンテンツ

`/var/www/example.com/oidc/index.shtml` の 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>
        OIDC_CLAIM_email=<!--#echo var="OIDC_CLAIM_email" --><br/>
        OIDC_CLAIM_email_verified=<!--#echo var="OIDC_CLAIM_email_verified" -->
        <br/>
      </p>
      <p>
        <img src="<!--#echo var="OIDC_CLAIM_picture" -->"
             alt="OIDC_CLAIM_picture" /><br/>
        OIDC_CLAIM_name=<!--#echo var="OIDC_CLAIM_name" --><br/>
        OIDC_CLAIM_given_name=<!--#echo var="OIDC_CLAIM_given_name" --><br/>
        OIDC_CLAIM_family_name=<!--#echo var="OIDC_CLAIM_family_name" --><br/>
      </p>
      <p>
        OIDC_CLAIM_locale=<!--#echo var="OIDC_CLAIM_locale" --><br/>
      </p>
      <p><a href="/oidc/redirect_uri?session=logout">ログアウト</a></p>
    </body>
  </html>
```

### 動作確認

再度ブラウザで動作確認画面を開くと、メールアドレス、アカウントに設定した画像、氏名などが表示されることが確認できました。

なお、d アカウント・コネクトに戻す（`etc/apache2/sites-available/example.com-ssl.conf` を元に戻して apache2 再起動する）と、REMOTE_USER 以外の情報は全く得られないことがわかります。両者で共通して得られるのは REMOTE_USER （つまり、iss クレームと sub クレーム）だけですね。

## 次回

本記事「3. Google アカウント編」では、d アカウント・コネクトではなく Google アカウントでソーシャルログインできるようにしてみました。次の記事は「[4. マルチプロバイダ編](https://qiita.com/trueroad/items/3d8a7dae83c7af66518b)」として d アカウント・コネクトと Google アカウントの両方でソーシャルログインできるようにします。