Shibboleth SPにおけるIdP独自attributeへの対応方法

#背景
前提記事：[Django + Shibboleth with RemoteUserMiddleware](https://qiita.com/hiro-jp/items/9d5a20baebc1c7d8f911)

IdPによっては、[urn](https://qiita.com/hiro-jp/items/9d5a20baebc1c7d8f911#attribute-map%E3%81%AE%E8%A8%AD%E5%AE%9A)で表すことのできない独自attributeを提供する場合も大いにあり得る。大企業などで社内ネットにSSOを実装している場合は独自attributeを持つ場合が多い（従業員番号、本部名など）。

#attribute-map.xml設定
`name`は独自attribute名。`nameFormat`をIdPが指定する形式にする必要がある。一般的には、`urn:oasis:names:tc:SAML:2.0:attrname-format:basic`でおおよそ対応できそうだ。

```xml:attribute-map.xml
...
    <Attribute name="X-Am-USERNAME" id="xusername" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"/>
...
```

#shibboleth2.xmlの設定
例えば上で設定した`xusername`を環境変数`REMOTE_USER`に格納したい場合は次のようにする。

```xml:shibboleth2.xml
...
    <ApplicationDefaults entityID="https://localhost/"
        REMOTE_USER = "xusername" # ← 変更
        cipherSuites="DEFAULT:!EXP:!LOW:!aNULL:!eNULL:!DES:!IDEA:!SEED:!RC4:!3DES:!kRSA:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1">
...
```


#実験
前提記事：[Apache + OneLogin SSO with Shibboleth](https://qiita.com/hiro-jp/items/096bbaf647a9e4a3ae18)

試しに、OneLoginから独自attributeをassertionに入れてみる。

Parametersから「＋」ボタンを押す。
![ss16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117020/ea5fb297-84bf-a887-683d-afee8015dc43.png)

独自の適当な名前を設定して「Include in SAML assertion」にチェックを入れる。
![ss17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117020/3b654d83-e4d6-af31-9011-219bc33fbc76.png)

値は「Macro」とでもしておいて、適当な文字列を設定する。
![ss18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117020/75d4c4f4-5251-3dc9-61a8-bb4a5c9851d3.png)

Saveすれば完了。SAML Tracerで見るとSAML応答に先ほど設定した独自assertionが含まれていることがわかる。

```text:SAML_Assertion
Issuer                      = https://app.onelogin.com/saml/metadata/～～～～
Subject                     = ************@yahoo.co.jp
NameID                      = ************@yahoo.co.jp

AttributeStatement:
 * urn:oid:1.3.6.1.4.1.5923.1.1.1.6                                   = ************@yahoo.co.jp
 * urn:oid:0.9.2342.19200300.100.1.3                                  = ************@yahoo.co.jp
 * urn:oid:2.5.4.4                                                    = *****
 * X-Am-USERNAME                                                      = free_text_here
 * urn:oid:2.5.4.42                                                   = *******

```

環境変数`REMOTE_USER`に値が入っていれば成功。

```
REMOTE_USER: free_text_here
```

**関連記事**：[Django + Shibboleth with RemoteUserMiddleware](https://qiita.com/hiro-jp/items/9d5a20baebc1c7d8f911)

#attributeをHTMLヘッダに格納する
Djangoアプリへのログインに用いるID情報は環境変数REMOTE_USERに格納するとして、そのほかに提供される情報もアプリ側で使いたい場合がある。この場合、HTTP Header情報に入れ込んでしまうのが手早い。

```httpd.conf
<Location />
    AuthType shibboleth
    ShibRequestSetting requireSession true
    Require shibboleth
    Require shib-session
    ShibUseHeaders On # ← 追加
</Location>
```
**注意**：HTTP Header情報は、少し知識のある人なら改竄が可能。アクセス制御のようなFatalなところに使用するパラメタはここに入れないようにする。詳しくは、[Shibboleth Wiki - AttributeAccess](https://wiki.shibboleth.net/confluence/display/SP3/AttributeAccess)を参照。

また、取得したattributeを識別できるよう、接頭辞を指定する。

```xml:shibboleth2.xml
    <ApplicationDefaults entityID="https://localhost/"
        REMOTE_USER = "givenName"
        cipherSuites="DEFAULT:!EXP:!LOW:!aNULL:!eNULL:!DES:!IDEA:!SEED:!RC4:!3DES:!kRSA:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1"
        attributePrefix="ATR_"> # ← 接頭辞を指定
```

すると、次のようなHTTP Headerが取得できる。

```
ATR_xusername: free_text_here
```

以上。