Auth0のQuick Start（Webアプリ）をやってみたメモ

最近、仕事で認証に関わることになりました。自分は認証に関しては全くの素人なので現在絶賛勉強中です。
今回、勉強の一環としてAuth0のQuick Startをやってみたので、そのメモです。
（Auth0を仕事で使うことになるかもしれないし）

# Quick Start
以下のAuth0の公式ドキュメントを見ながらアプリを立ち上げます。
https://auth0.com/docs/quickstarts

今回自分はRegular Web Application（node.js）のサンプルをダウンロードして試してみました。ドキュメント通りに進めれば本当に数分程度でAuth0の認証機能が組み込まれたWebアプリをたちあげることができます。Auth0の公式ドキュメントがかなりいい感じにまとまっているので、まずは公式をみて作業してみることをお勧めします。
Quick Stratの手順については特に書くことがないので、以降はサンプルアプリに対して自分が試してみたことのメモです。

# 取得したトークンの確認
まずはサンプルアプリにログインしてみて、アプリ側にトークンが渡ってきているか確認してみます。
ソースコードに```console.log()```を仕込んでみて表示させてみます。

```javascript:app.js
var strategy = new Auth0Strategy(
  {
    domain: process.env.AUTH0_DOMAIN,
    clientID: process.env.AUTH0_CLIENT_ID,
    clientSecret: process.env.AUTH0_CLIENT_SECRET,
    callbackURL:
      process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/callback'
  },
  function (accessToken, refreshToken, extraParams, profile, done) {
    console.log(accessToken);  // 追加
    console.log(refreshToken); // 追加
    console.log(extraParams);  // 追加
    return done(null, profile);
  }
);
```

```
// アクセストークン
hpblVqJ1veii7uaM 〜略〜
```
```
// リフレッシュトークン
undefined
```
```
// extraPrams
{ access_token: 'hpblVqJ1veii7uaM 〜略〜',
  id_token:
   'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1Ni 〜略〜',
  scope: 'openid profile email',
  expires_in: 86400,
  token_type: 'Bearer' }
```

アクセストークンが取得できていることが確認できましたが、リフレッシュトークンは取得できていませんね。
extraParamってなにかな？と思っていましたが、結果をみるに中身はアクセストークンとIDトークンみたいです。

# アクセストークンが使えるか確認
このアクセストークンを使うとAuth0が提供するAPIを実行することができます。
アクセストークンに応じたユーザー情報を返却するAPIとして```/userinfo```というエンドポイントがあるので、アクセストークンを抜き取ってcurlコマンドでAPIを直接叩いてみます。

```
curl --request GET \
  --url https://{YOUR_DOMAIN}/userinfo \
  --header 'authorization: Bearer hpblVqJ1veii7uaM 〜略〜 ' \
  --header 'content-type: application/json'
```

```json-doc

HTTP/1.1 200 OK
〜略〜

{
  "sub": "auth0|xxxxxxxxxxxxxxxxxxxxxxxx",
  "nickname": "xxxxx",
  "name": "XX XX",
  "picture": "https://xxx",
  "updated_at": "xxxx-xx-xxxxx:xx:xx.xxxx",
  "email": "xxxxx@xxx",
  "email_verified": false
}
```
ほぼ伏せ字ですが…、ユーザー情報が返ってくることが確認できました。

# IDトークンをデコード
続いて、IDトークンの確認をしてみます。
https://jwt.io/ にIDトークンを貼り付けると署名検証とデコードをしてくれるので、こちらを利用します。
結果は以下になりました。

```json-doc
// HEADER
{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "QTJCRDQ2NTIzM〜略〜"
}
```
```json-doc
// PAYLOAD
{
  "nickname": "xxxxx",
  "name": "XX XX",
  "picture": "https://xxx",
  "updated_at": "xxxx-xx-xxxxx:xx:xx.xxxx",
  "email": "xxxxx@xxx",
  "email_verified": false,
  "iss": "https://{YOUR_DOMAIN}/",
  "sub": "auth0|xxxxxxxxxxxxxxxxxxxxxxxx",
  "aud": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "iat": 1567396917,
  "exp": 1567432917
}
```
```json-doc
// VERIFY SIGNATURE
RSASHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
)
```

# リフレッシュトークンを取得する
Quick Startそのままではリフレッシュトークンが取得できなかったので、ちょっと手を入れてみます。
まずはAuth0のDashBoardから対象アプリのAdvanced SettingsのGrant Typeタブをみてリフレッシュトークンのチェックボックスにチェックが入っていることを確認します。
次にアプリ側ですが、[Auth0のドキュメント](https://auth0.com/docs/tokens/refresh-token/legacy#obtain-a-refresh-token) によるとリフレッシュトークンを取得するには最初の認可リクエストの```scope```パラメータに```offline_access```を追加する必要があるようです。

```javascript:routes/auth.js
router.get('/login', passport.authenticate('auth0', {
  // scope: 'openid email profile'
  scope: 'openid email profile offline_access' // offline_accessを追加
}), function (req, res) {
  res.redirect('/');
});
```

先ほどは```undefined```だったリフレッシュトークンが取得できました。

```
// リフレッシュトークン
1Z9hMroGWiIkL 〜略〜
```

# リフレッシュトークンを使ってみる
リフレッシュトークンを使ってアクセストークンを取得してみます。


```
curl --request POST \
  --url 'https://{YOUR_DOMAIN}/oauth/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=refresh_token \
  --data client_id=xxxxxxxxxxxxxxxxxxxxxxxx \
  --data client_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
  --data refresh_token=1Z9hMroGWiIkL 〜略〜
```

新しいアクセストークンとIDトークンが取得できました。

```JSON
{
  "access_token": "ChNVdSmA 〜略〜 ",
  "id_token": "eyJ0eXAiOiJKV1QiLCJ 〜略〜 ",
  "scope": "openid profile email offline_access",
  "expires_in": 86400,
  "token_type": "Bearer"
}
```

# 感想
Quick Startをやっただけですが、Auth0はとても使いやすいサービスだと思いました。
ドキュメントが英語だったので最初は戸惑いましたが、Google翻訳を活用しつつ落ち着いて読めば、おおよその内容がわかるぐらい丁寧に解説されています。
特にOAuth2.0やOpenID Connectを知っている人なら、すんなり使えるんじゃないでしょうか。

もっとAuth0の使い方をもっと勉強していきたいと思います。