OpenAMから連携できるユーザー属性を追加する

## ユーザーの属性情報の連携

昨日はApacheにmod_auth_openidcという**ApacheをRelying Partyとして動作させるモジュール**を導入し、実際にFederationをやってみました。このとき要求した情報の範囲(scope)は`openid`と`profile`でした。

以下は、実際にOpenID Providerから連携した情報(profile)になります。

<img width="550" alt="001.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/1baba75a-e62c-c2d9-5f43-92b655c4a152.jpeg">

上述のように、profileっていうscopeを要求した時は、**「`Full name`、`Family name`、`Given name`を連携するよ～？」**っていう同意画面が表示され、実際にRelying Partyに連携されます。

ただ、会社のアプリケーションを動作させるには、他にも欲しい情報があったりします。例えば、

* 所属
* 役職
* 権限グループ（AD上のSecurity Groupの情報）

こういった情報が認証時に連携される前提があれば、業務アプリケーションを作るのが（主に権限まわり）が捗ると思いませんか？きっと捗るはず！^^なので、今日は連携するユーザーの属性情報を増やしてみましょう。

## 会社っぽい属性を持ったユーザーを追加

今日はこれまで使っていた検証用アカウント（ユーザー名は`johnd`）は使わずに、新たに**会社っぽいユーザー属性を持ったユーザー**を追加して、そのユーザーの属性を連携するという方針で行きます。

まず、以下のLDIF（ファイル名は`sample.ldif`）を作成します。構成はシンプルです。

* `INFOSYS01`って組織がある
* `gnanashi`ってユーザーがいる
* `gnanashi`は`INFOSYS01`に所属している
* `gnanashi`は`Manager`である

```
dn: cn=INFOSYS01,ou=groups,dc=openam,dc=forgerock,dc=org
changetype: add
objectClass: groupofuniquenames
objectClass: top
cn: INFOSYS01
uniqueMember: uid=nanashi,ou=people,dc=openam,dc=forgerock,dc=org

dn: uid=gnanashi,ou=people,dc=openam,dc=forgerock,dc=org
changetype: add
objectClass: inetuser
objectClass: iplanet-am-managed-person
objectClass: kbaInfoContainer
objectClass: iplanet-am-auth-configuration-service
objectClass: devicePrintProfilesContainer
objectClass: sunFederationManagerDataStore
objectClass: inetorgperson
objectClass: forgerock-am-dashboard-service
objectClass: sunFMSAML2NameIdentifier
objectClass: sunIdentityServerLibertyPPService
objectClass: top
objectClass: iPlanetPreferences
objectClass: sunAMAuthAccountLockout
objectClass: pushDeviceProfilesContainer
objectClass: organizationalperson
objectClass: person
objectClass: iplanet-am-user-service
objectClass: oathDeviceProfilesContainer
cn: gonbei nanashi
sn: nanashi
givenName: gonbei
memberOf: cn=INFOSYS01,ou=groups,dc=openam,dc=forgerock,dc=org
title: Manager
departmentNumber: INFOSYS01
inetUserStatus: Active
uid: gnanashi
userPassword: password
```

OpenAMがインストールされたサーバーには**ldap某系のコマンド**が配置されますので、その中の**ldapmodify**コマンドを使って、作成したLDIFでユーザーとグループを作成します。

```bash
$ sudo /home/openam/openam/opends/bin/ldapmodify -D "cn=Directory Manager" -w password -h localhost -p 50389 -f ~/sample.ldif
```

## 追加したユーザーの属性をOpenAMの検索対象に加える

本連載で用意しているOpenAMのユーザーリポジトリは内蔵(embedded)のLDAPを使用しています。この場合、OpenAMは**あらかじめ設定されたユーザーの属性しか検索対象に加えない構成**となっています。よって、明示的に`departmentNumber`や`title`を検索対象としてやる必要があります。

**Top Realm Level => Data Stores => embedded**をクリックする。

**LDAPユーザー属性**に`departmentNumber`や`title`を追加してやる。（`memberOf`はデフォルトで検索対象となっています。）

<img width="796" alt="002.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/649c17c3-f427-23b4-ce6b-42b3ef165df0.jpeg">

## profileのscopeで連携する属性を追加する

昨日設定したmod_auth_openidcは`scope=openid profile`と指定して、ユーザーの情報を要求する設定となっています。今回はここの設定は変更せず、**profileというスコープを要求されたら、役職や所属のユーザー属性を連携する**という設定をします。

**Top Realm Level => Scripts => OIDC Claims Script**をクリックします。

<img width="898" alt="003.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/02635f76-2ed5-d19c-e3ee-c581f1da542d.jpeg">

GROOVYで書かれたコードがブラウザ上に表示されます。このコードの**64行目以降**を以下のように編集します。変更内容としては以下の2点です。

* 連携する対象のユーザー属性に`memberOf`、`departmentNumber`、`title`を追加
* profileというscopeに上述の3つのユーザー属性を含む

```groovy
// [ {claim}: {attribute retriever}, ... ]
claimAttributes = [
        "email": attributeRetriever.curry("mail"),
        "address": { claim, identity, requested -> [ "formatted" : attributeRetriever("postaladdress", claim, identity, requested) ] },
        "phone_number": attributeRetriever.curry("telephonenumber"),
        "given_name": attributeRetriever.curry("givenname"),
        "zoneinfo": attributeRetriever.curry("preferredtimezone"),
        "family_name": attributeRetriever.curry("sn"),
        "locale": attributeRetriever.curry("preferredlocale"),
        "name": attributeRetriever.curry("cn"),
        "memberOf": attributeRetriever.curry("memberOf"),
        "departmentNumber": attributeRetriever.curry("departmentNumber"),
        "title": attributeRetriever.curry("title")
]

// {scope}: [ {claim}, ... ]
scopeClaimsMap = [
        "email": [ "email" ],
        "address": [ "address" ],
        "phone": [ "phone_number" ],
        "profile": [ "given_name", "zoneinfo", "family_name", "locale", "name", "memberOf", "departmentNumber", "title" ]
]
```

## 動作確認

昨日と同様に、Federationされたユーザー属性を確認するので、Relying Party上に配置したphpinfo()を実行するコンテンツにアクセスします。（本記事では`https://rp.example.com/cgi-bin/phpinfo.php`）

ユーザー認証の画面が表示されるので、今回LDIFで追加したユーザー（ユーザー名は`gnanashi`）でサインインします。

<img width="477" alt="004.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/e9e84910-01e4-b282-4272-55fe4b8c8d8a.jpeg">

認証後、Federationするユーザー属性の連携の同意画面が表示されます。ここで連携するユーザー属性を確認すると、今回追加を行った**3つのユーザー属性**が付加されています。

<img width="445" alt="005.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/17d073a0-7a95-0d5a-dfd7-9a5c99449a12.jpeg">

同意後、Relying Party上のphpinfo()が実行され、PHPアプリケーションに連携されているHeader情報が出力されます。
ばっちり、追加を行った**3つのユーザー属性**が連携されています。


<img width="742" alt="006.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/148404/2fb23377-1b44-2b72-822b-8682ebdadfed.jpeg">


## まとめ

今日のまとめ(´ρ`)

* アプリケーションに連携するユーザー属性はカスタマイズできる
* 既存のscopeに追加できる
* （本記事ではやってないけど、）新たにオリジナルのscopeを追加して、そこに新たに連携するユーザー属性を追加することもできる

ちなみに一番最後のやつをやるときは、Relying Partyの設定で、要求可能なスコープにも追加してやる必要があったりします。

そろそろ折り返しかな？？後半戦もがんばる！

ばい！