Self-Issued OP 確認してみた @ Recruit ポンパレ 

#Self-Issued OP 確認してみた @ Recruit ポンパレ
先日、2018/3/23金に開催された、OpenID Technight #15に参加した際、そこで紹介のあった OpenID Connect Self-issued OP について、下記にメモ書きしていたのですが、
> OpenID Connect Self-issued OP概要 ~OpenID Technight #15より~
> https://qiita.com/SAM-l/items/93b56c6061cfbb6653ec

その際「iPhoneのポンパレモールアプリで実際に動いている様子を見れるってよ」
ということだったので、実際にポンパレモールでやりとりされている電文を覗いてみました:grinning::grinning: 

以下、覗いた結果です。

##環境情報

- 端末
    - iOS 11.3
    - ポンパレモールアプリ 2.1.7

- 電文の確認に使ったもの
    - Mac OS High Sierra 10.13.4
    - Burp Proxy 1.7.33

- 確認日
    - 2018年4月24日(火)

##概要シーケンス

やりとりされている内容を見る限り、ざっくり下記のようなシーケンスになっている事が確認できました。

- 青色部分
    - リクルート内の共通OP（リクルートポイント）での認証&認可のフロー
- 赤色部分
    - Self-issued OPもどきのフロー

![シーケンス.png](https://qiita-image-store.s3.amazonaws.com/0/246440/32568599-e09f-3cc7-f9f9-8469106c4b51.png)

以降、詳細を記しますが、

- パラメータを見やすくするため本来存在しない改行をいれてます
- 「*****」でマスクされている箇所には実際は文字列が入っていました

ご了承ください。

###1. ボタン押下
- ポンパレモールのアプリを開き、「次へすすむ」ボタンを押下する
- 一度ログインしてしまっていたので、「*****でログインする」の文言が表示されているもよう

![ポンパレ-1.png](https://qiita-image-store.s3.amazonaws.com/0/246440/5ead2a9c-6eba-625d-ff2e-2398e93ac8fd.png)![ポンパレ-2.png](https://qiita-image-store.s3.amazonaws.com/0/246440/7f0a1902-d076-65cb-f165-3a152f650705.png)

###2. 共通OPにAuthZ Req
- ボタンを押下すると、送付されたリクエストが下記
- `code_challenge`や`code_challenge_method`が送付されており、PKCEに対応している事がわかる:point_up:
- `thumbprint`で送られている値は、「5. Self-issued OP AuthZ Res」で送付される`id_token`の`sub`の値

```HTTP:AuthZReq
POST /member/OIDCLogin/?
scope=openid%20r_profile%20r_email%20r_phone%20r_address%20r_ml_magzn%20r_etc&
state=*****&
client_id=*****&
response_type=code&
login_hint=*****&
redirect_uri=https://mypage.ponparemall.com/member/distributionOidc/?appCd=2&
sc_ap=1&
sc_vid=***** HTTP/1.1
Host: point.recruit.co.jp
Content-Type: application/x-www-form-urlencoded

code_challenge=*****&
code_challenge_method=S256&
thumbprint=*****
```

###3. Self-issued OP に AuthZ Req
- Self-issued OP に対応しているアプリであることを確認
    - 判断基準はよくわかりません
- 確認できたら Self-issued OP に AuthZ Req
- Self-issued OP 未対応のアプリではおそらく下記の流れ
   - AuthZ Req を受けて「リクルートポイント」が認証画面を出す
   - ID/PWDで認証を行う
   - 「6 .共通OP AuthZ Res」へ
- カスタムスキーム経由ではなく「https://point.recruit.co.jp/member/OIDCLogin/verify 」へのリクエストをSelf-issued OP へのAuthZ Reqと判断しているもよう

```HTTP:SIOP_AuthZReq
HTTP/1.1 302 Found
Location: https://point.recruit.co.jp/member/OIDCLogin/verify/?
state=*****&
nonce=*****&
scope=openid&
response_type=id_token&
key_state=registered&
client_id=https%3A%2F%2Fpoint.recruit.co.jp%2Fmember%2FOIDCLogin%2Fverify%2F
```

###4. 認証
- 初回はID/PWDで認証
- 以降は画面遷移のみでユーザの操作なし

###5. Self-issued OP AuthZ Res
- 以前やりとりした証明書情報で生成されたid_tokenが発行される

```HTTP:SIOP_AuthZRes
GET /member/OIDCLogin/verify/?id_token=*****&state=***** HTTP/1.1
Host: point.recruit.co.jp
```
- 実際のid_tokenの内容はこんな感じ

```JSON:id_token(header)
{
  "typ" : "JWT",
  "alg" : "RS256"
}
```
```JSON:id_token(body)
{
  "iat" : 1524571670,
  "r_terminfo" : "iPhone9,2",
  "iss" : "https:\/\/self-issued.me",
  "sub" : "*****",
  "sub_jwk" : {
    "kty" : "RSA",
    "n" : "*****",
    "e" : "AQAB"
  },
  "aud" : "https:\/\/point.recruit.co.jp\/member\/OIDCLogin\/verify\/",
  "exp" : 1524573470,
  "nonce" : "*****"
}
```

###6. 共通OP AuthZ Res
- Self-issued OP からの`id_token`の検証をもって、認証完了、レスポンスを返却
- リダイレクトが以下の通り何回も走ってた

```HTTP:AuthZRes-1
HTTP/1.1 302 Found
Location: https://point.recruit.co.jp/member/twoStepAuth/oidcLoginAuth/?
scope=openid+r_profile+r_email+r_phone+r_address+r_ml_magzn+r_etc&
auth_transct_id=*****&
response_type=code&
state=*****&
insertion_flg=&
prompt=&
nonce=&
redirect_uri=https%3A%2F%2Fmypage.ponparemall.com%2Fmember%2FdistributionOidc%2F%3FappCd%3D2
```

```HTTP:AuthZRes-2
HTTP/1.1 302 Found
Location: https://point.recruit.co.jp/member/OIDCConsent/?
scope=openid+r_profile+r_email+r_phone+r_address+r_ml_magzn+r_etc&
auth_transct_id=*****&
response_type=code&
redirect_uri=https%3A%2F%2Fmypage.ponparemall.com%2Fmember%2FdistributionOidc%2F%3FappCd%3D2&
state=*****&
sc_ap=1&
client_id=*****&
sc_vid=*****
```

- ようやく`code`が渡された
 
```HTTP:AuthZRes-3
HTTP/1.1 302 Found
Location: https://mypage.ponparemall.com/member/distributionOidc/?
appCd=2&code=*****&
state=*****&
sc_ap=1&
sc_vid=*****
```

###7. 共通OPに Token Req
- AuthZCode で AccessToken要求
    - でも`grant_type`も`redirect_uri`もないね:thinking:独自仕様かな
- [PKCE](https://tools.ietf.org/html/rfc7636) に対応しているため、`code_verifier`の送付必要:exclamation:
    - でもパラメータ名がCamelCaseだね:thinking:

```HTTP:TokenReq
POST /1_1_0/accessTokenIssueOidc/ HTTP/1.1
Host: auth.api.ponparemall.com

appCd=2&
autoLoginFlg=1&
code=*****&
codeVerifier=*****&
deviceUUId=*****&
format=json&
key=*****
```

###8. 共通OP Token Res
- 要求したscopeにアクセスするためのAccessTokenが発行される
- `rLoginHint`の値には「5. Self-issued OP AuthZ Res」で送付される`id_token`の`sub`の値が
- `rUserDisplayName`の値にはログイン時に使ったメールアドレスが
- Token Responseも何かちょっと違うね:thinking:

```HTTP:TokenRes
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8

{
  "authInfo":
    {
      "accessToken":"*****",
      "accessTokenRefreshExpireTs":"2018/04/24 21:37:50",
      "secretToken":"*****",
      "rCapMemberId":"*****",
      "rUserDisplayName":"*****",
      "rLoginHint":"*****"
    }
}
```

##おわりに
ところどころ、Recruitさま独自仕様っぽいものが発見されて面白かったです。
お買い物をするとインタラクション必須となるフローが走るとのことだったのでそちらも試したいところですが、明日早朝からロケなのでここで一旦中断します:woman_tone1::woman_tone1: