Yahoo! ID連携(v1)でアクセストークンを取得する手順をHTTPだけで説明する

本稿ではYahoo! ID連携(v1)でアクセストークンを取得する手順をHTTPだけで説明する。

## 前提条件

* すでに[アプリケーションの登録](https://e.developer.yahoo.co.jp/register)が済んでいること。
    * ショッピング関係のAPIを利用するアプリについては、[アプリケーション情報の入力 (Yahoo!ショッピング ストア運営をサポートするAPIの利用)](https://e.developer.yahoo.co.jp/shopping/register)から登録する必要がある。

## Authに必要な情報を用意しておく。

[アプリケーションの管理](https://e.developer.yahoo.co.jp/dashboard/)からアプリケーションの詳細ページを開き、下記の情報を控えておく。

* アプリケーションID
* シークレット
* コールバックURL

アプリケーションの詳細ページ:

<img width="963" alt="Developers__39__Store：アプリケーションの管理：Yahoo_デベロッパーネットワーク.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/a7d11e97-fce1-b956-44e4-e7dc22cc3417.png">


## ユーザー認可リクエスト(認可トークンを取得する)

次のようなHTTPリクエストを送ると

```http:リクエスト
GET /yconnect/v1/authorization?response_type=code+id_token&client_id=${アプリケーションID}&redirect_uri=${コールバックURL}&nonce=${適当な数字} HTTP/1.1
Host: auth.login.yahoo.co.jp
Accept: */*
Connection: keep-alive
```

次のようなレスポンスが帰ってくる。

```http:レスポンス
HTTP/1.1 302 Found
Age: 0
Cache-Control: no-cache, no-store, must-revalidate, private
Connection: close
Content-Length: 0
Content-Type: text/html; charset=EUC-JP
Date: Wed, 17 Apr 2019 09:17:51 GMT
Location: https://login.yahoo.co.jp/config/login_verify2?.src=oauth&.display=&ckey=${アプリケーションID}&.done=https%3A%2F%2Fauth.login.yahoo.co.jp%2Fyconnect%2Fv1%2Fauthorization%3Ftoken%3Dxxxxxxx%26from_login%3D1%26.scrumb%3D0%26display%3D&auth_lv=pin
P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p_jp.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
Server: ATS
```

この`Location`ヘッダにあるURLをブラウザで開くと、アプリへの情報提供同意画面が表示される。

<img width="554" alt="同意画面_-_Yahoo__JAPAN.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/504e33a6-7953-843a-4d06-8c779e4dae1d.png">

同意すると、`http://コールバックURL?code=XXXXX&state=`にリダイレクトされる。この`code`パラメータの値が**認可トークン**と呼ばれるものになる。

詳細: [Yahoo! ID連携:Authorizationエンドポイント - Yahoo!デベロッパーネットワーク](https://developer.yahoo.co.jp/yconnect/v1/server_app/explicit/authorization.html)

## アクセストークン要求(アクセストークンを取得する)

Basic認証の情報を用意する。下記のコードで計算しておく。(HTTPだけで説明すると言ったが下はPHPコード)

```php
$Basic認証の情報 = base64_encode($アプリケーションID . ':' . $シークレット);
```

アクセストークンを取得するために、次のようなHTTPリクエストを送る。認可トークンは上のステップで取得したもの。

```http:リクエスト
POST /yconnect/v1/token HTTP/1.1
Host: auth.login.yahoo.co.jp
Accept: */*
Authorization: Basic {$上で計算したBasic認証の情報}
Content-Type: application/x-www-form-urlencoded; charset=utf-8

grant_type=authorization_code&code={$認可トークン}&redirect_uri=${コールバックURL}
```

次のようなレスポンスが帰ってくる。

```http:レスポンス
HTTP/1.1 200 OK
Age: 0
Cache-Control: no-cache, no-store, must-revalidate, private
Cache-Control: no-store, private
Connection: close
Content-Encoding: gzip
Content-Length: ????
Content-Type: application/json;charset=UTF-8
Date: Wed, 17 Apr 2019 09:18:09 GMT
P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p_jp.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
Pragma: no-cache
Server: ATS
Vary: Accept-Encoding

{
    "access_token": "アクセストークン(めっちゃ長い)",
    "expires_in": "3600",
    "id_token": "IDトークン(そこそこ長い)",
    "refresh_token": "リフレッシュトークン(そんなに長くない)",
    "token_type": "bearer"
}
```

ボディにある`access_token`が**アクセストークン**になる。

詳細: [Yahoo! ID連携:Tokenエンドポイント - Yahoo!デベロッパーネットワーク](https://developer.yahoo.co.jp/yconnect/v1/server_app/explicit/token.html)


## 関連

* [yahoo-id.sh: Yahoo APIのアクセストークンを取得する開発ツール - Qiita](https://qiita.com/suin/items/a40bb903604e9f3215f9#_reference-49575b56dae22f98104d)
* [Yahoo APIでアクセストークン有効期限切れのレスポンスサンプル - Qiita](https://qiita.com/suin/items/5241f461d8ced89f1091)
* [Yahoo APIのアクセストークンとリフレッシュトークンの有効期限 - Qiita](https://qiita.com/suin/items/6a67c999cfdd613ba497#_reference-8350c3d9edcfe81dac8c)