【LinkedIn】OAuth2 API まとめ

# 背景

こんにちは。@ight です。最近いろんなサービスの OAuth2 や OpenID Connect などの認証/認可まわりを勉強しています。

今回はひょんなことから **LinkedIn の OAuth2 Authentication** で REST API を叩き、LinkedIn の情報を取ってくる機会があったのでやってみました。

実際アプリケーションを書くときには独自実装せずに既存のライブラリを使えば良いと思うんですが、今回はあえてパラメータを確認しながら REST API を叩くところまでやってみたいと思います。

[Authenticating with OAuth 2.0 - LinkedIn Developer Network](https://developer.linkedin.com/docs/oauth2) に従って進めていきます。
OAuth2 と呼んでいるのは [RFC 6749](https://tools.ietf.org/html/rfc6749) のことです。

# いきなりのまとめ!

* Access Token 取得までは **OAuth2 からそんなに外れてなく**て、そんなにハマりどころはない
* Access Token の**有効期間は60日**で、**Refresh Token はない**
* REST API はデフォルトは `text/xml` で返却される
* 様々な API を叩くためには **[Partnership Programs](https://developer.linkedin.com/partner-programs) に登録し、審査を通過する必要がある**！
* Client 登録が会社名とかいろいろ登録する必要があって、ちょっとダルい

## 様々な API を叩くためには Partnership Programs に登録し、審査を通過する必要がある

例えば、ユーザーのつながり関係を取得する [Connections API](https://developer.linkedin.com/docs/guide/v2/people/connections-api)  (Facebook でいう Friend Edge) は `r_network` scope を求められますが、実はその scope のためには **[LinkedIn's Partnership Programs](https://developer.linkedin.com/partner-programs)** というものに登録する必要があります。

「事前にテストできないの？」って思ったんですが、(自分の探した限りでは) テスト用の Client は見つからず、この Program に登録しないと Connections API は叩けないようでした。

じゃあ簡単に登録できるのかというとどうやらそうでもなさそうで、[Frequently Asked Questions](https://developer.linkedin.com/support/faq) には

> We aim to respond to all application inquiries within 15 days.

「15日以内を目標に、合否連絡をするよ」って感じです。15日...全然手軽じゃない...。

LinkedIn 連携を考える前には、あらかじめ**やりたいこと**と**できること**を吟味していた方が良さそうです。
(自分は Connections API が使いたかった...)

# 実際に REST API を叩くまでやってみる
## Step 1 - Configuring your LinkedIn application

[こちら](https://www.linkedin.com/secure/developer?newapp=) から LinkedIn Application を登録することができます。
他社の Client 登録と違って**会社の情報を登録する**必要があります。今回は適当に埋めて進みます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/119734/2f22f0a2-4626-3326-b886-ef882196e83b.png" height="600px">

完了すると **Client ID と Client Secret が払い出され**ます。メモしておきましょう。


![スクリーンショット 2018-04-22 22.32.37.png](https://qiita-image-store.s3.amazonaws.com/0/119734/4ca57afb-3e3f-e498-8302-cd77bca58b35.png)

おそらく scope の命名規則として `(read/write)_(対象)` となっているようです。
前述の通り、ここでは4つまでしか選択することができません。

## Step 2 — Request an Authorization Code

それでは Authorization Request を投げていきます。

```bash
$ CLIENT_ID=#先ほどメモした CLIENT ID
$ CLIENT_SECRET=#先ほどメモした CLIENT SECRET
$ REDIRECT_URI=https://localhost

$ open "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&state=987654321&scope=r_basicprofile"
```

全て OAuth2 に沿ったパラメータ名ですね。よかった。
ちなみにユーザーが同意に cancel をすると error パラメータが返却されますが、OAuth2 に定義されている error code ではなく

* `user_cancelled_login`
* `user_cancelled_authorize`

が返ってくるようです。

## Step 3 — Exchange Authorization Code for an Access Token

ついに Access Token を取得しましょう！

```bash
$ CODE=...

$ curl -X POST \
  --data "grant_type=authorization_code" \
  --data "code=${CODE}" \
  --data "redirect_uri=https://localhost" \
  --data "client_id=${CLIENT_ID}" \
  --data "client_secret=${CLIENT_SECRET}" \
  "https://www.linkedin.com/oauth/v2/accessToken" | jq
{
  "access_token": "xxxx",
  "expires_in": 5183999
}
```

`expires_in` に+1して計算すると、60日分の Access Token になっているようです。`token_type` は返ってきていませんが bearer です。


## Step 4 — Make authenticated requests

いよいよ REST API を叩いてみましょう。

```bash
$ curl -X GET -H "Authorization: Bearer ${ACCESS_TOKEN}" 'https://api.linkedin.com/v1/people/~'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
  <id>XXXXXXXXXX</id>
  <first-name>なまえ</first-name>
  <last-name>みょうじ</last-name>
  <headline>会社名がはいるよ</headline>
  <site-standard-profile-request>
    <url>https://www.linkedin.com/profile/view?id=_idididid&amp;authType=name&amp;authToken=lYnD&amp;trk=api*a5218725*s5537155*</url>
  </site-standard-profile-request>
</person>
```

おお、そうでした! デフォルトでは XML で返却されるんでした！ `?format=json` をつけましょう！

```bash
$ curl -X GET -H "Authorization: Bearer ${ACCESS_TOKEN}" 'https://api.linkedin.com/v1/people/~?format=json'
{
  "firstName": "なまえ",
  "headline": "会社名がはいるよ",
  "id": "XXXXXXXXXX",
  "lastName": "みょうじ",
  "siteStandardProfileRequest": {"url": "https://www.linkedin.com/profile/view?id=_idididid&authType=name&authToken=lYnD&trk=api*a5218725*s5537155*"}
}
```

なぜか最初から少しだけ成形された JSON で返ってきました。

## Step 5 — Refresh your Access Tokens

> To refresh an Access Token, simply go through the authorization process outlined in this document again to fetch a new token. 

Refresh したかったらもういい一度このフローをやり直してね的なことが書かれてます。Refresh Token 的なのはなさそうですね。
ちなみにすでに認可済みの場合は、認可画面スキップしてくれる仕様のようです。