自分のアプリやWebサービスにAuth0で簡単にユーザ認証を追加する方法

# 認証サーバの役割

- ユーザの登録・管理・ログイン・ログアウト
- セキュアな認証

こういうのってガチで作ろうとしたらRFC読みながら、、、とか、かなり大変。
それにプログラムは書けば書くほどバグが生まれるので、、、何も書かずに済むのが一番です :smile: 
そこで**Auth0**の出番です。

# [Auth0](https://auth0.com/jp/) とは

[Auth0](https://auth0.com/jp/)は認証サーバのWebサービス。
競合にはAWS Cognito User PoolやFirebaseなどがある。
~~正直AWS Cognito User Pool 使いたいすよね~~

# デモ

とりあえず自分のREST-APIサーバへのアクセスに認証を入れてみる。
やりたいことをUMLで書くとこんな感じです。
<img width="354" alt="スクリーンショット 2017-03-28 16.06.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/87900/c5056f22-28ad-a61e-b98c-e50a2cbc7474.png">

## Auth0 ユーザ登録

https://manage.auth0.com/login

省略
## Client を作成

![Screenshot 2017-03-28_14-47-45.png (63.6 kB)](https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/4f5f1468-4187-4c16-bd17-abc57977349b.png)

## 今作った Client の詳細を開く
![Screenshot 2017-03-28_15-06-18.png (68.9 kB)](https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/cd1385e3-cc38-4758-80ff-9565002b9546.png)
**Domain** と **Client ID** と **Client Secret** をメモ。
[Postman](https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=ja)で作業を行っていきます。

## [Signup API](https://auth0.com/docs/api/authentication#signup) で認証するユーザを作成
![Screenshot 2017-03-28_15-12-19.png (51.6 kB)](https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/beb19954-b90c-4a35-be30-b041faf25338.png)

||value|
| --- | --- |
| client_id | さっきメモしたやつ  |
| email | なんでもOK  | 
| password | なんでもOK |
| connection | Username-Password-Authentication |
Username-Password-Authentication は ユーザ名とパスワードで認証する方式です。
このときのパスワードの長さとかバリデーションルールは
 Connections→DatabaseのUsername-Password-Authentication
とかで色々変更できます。
ちなみにusername or email  + password で認証できるようにすることも出来ます。

## [Login API](https://auth0.com/docs/api/authentication#database-ad-ldap-active-) でトークンを取得する

今作ったユーザでログイン+認証してみる。
![Screenshot 2017-03-28_15-23-19.png (52.6 kB)](https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/17c7ad57-e4b3-4c03-9907-40f7d99f0244.png)

するとこんな感じのレスポンスが返ってくるはず。

<img width="708" alt="スクリーンショット 2017-03-28 15.24.01.png (47.0 kB)" src="https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/e0fbd28d-e27e-4217-ba80-03a97df53203.png">

この **id_token** を自鯖のAPIにリクエストする際に利用する。
※含まれてる**access_token** は auth0 へアクセスするときのアクセストークンなので今回は使わない

## 自鯖APIを用意する

面倒なので [webtask](https://webtask.io/) を利用します。
webtaskのユーザ登録する。

ちなみに登録画面とかのデザインが見覚えがありますね。
実はauth0は内部的にwebtaskを利用しているそうです。
競合はNowですかね。

ということで省略。

登録が終わると、こんな画面が出てくるはず。
![Screenshot 2017-03-28_15-31-12.png (115.5 kB)](https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/18022bc0-6f0d-4376-80bc-9396fef8fa3f.png)

1, 2 を終わらせて、3は飛ばして、`wt edit` とコマンドを打つ。

するとブラウザが開いてこんな画面が表示されます。

<img width="605" alt="スクリーンショット 2017-03-28 15.33.29.png (49.4 kB)" src="https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/28881974-464f-41ca-a74d-57ebe09ae175.png">

webtask を選択して名前はなんでもOKで作成する。

ソースコードに以下をコピペします。

```js
"use latest";
module.exports = function(ctx, cb) {
  let result = 'fail';
  const jwt = require('jsonwebtoken@7.1.9');
  const secret = ctx.secrets.clientSecret;
  const authorization = ctx.headers.authorization || '';
  const tokens = authorization.split(' ');
  if (tokens[0] == 'Bearer') {
    const jwtToken = tokens[1];
    let decoded;
    try {
      const decoded = jwt.verify(jwtToken, secret);
      result = 'success';
    } catch(err) {
      console.log(err);
    }
  }
  cb(null, { result });
};
```

コードではjsonwebtokenの認証をして、成功したら success、失敗したら fail を返してます。
※ちなみに webtask で使える node modules は[ここ](https://tehsis.github.io/webtaskio-canirequire/)で検索できる。

これだけでは動かないので、 結構前にメモした Client secret (ソースコード5行目)を渡すようにします。
1. tool ボタンから Secrets を選択。
<img width="943" alt="スクリーンショット 2017-03-28 15.37.02.png (218.8 kB)" src="https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/7e428f1c-9cc1-4c7e-aff8-40de9c115752.png">

2. clientSecret という名前で作成。
<img width="267" alt="スクリーンショット 2017-03-28 15.38.00.png (25.5 kB)" src="https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/ab74e165-db74-4258-b600-b851b3b850b2.png">

3. Run ボタンを押して実行
<img width="112" alt="スクリーンショット 2017-03-28 15.40.47.png (12.1 kB)" src="https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/b6addabe-89c1-4055-833d-d0e5c9563bd1.png">

4. 一番下にURLが表示されてるのでコピー
![Screenshot 2017-03-28_15-42-31.png (13.3 kB)](https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/8b621a6d-aba8-4ab5-b96b-d906602e9a3f.png)

5. postman で トークンを渡してAPIアクセスしてみる

||value|
| --- | --- |
| Authorization  | Bearer さっきの`id_token` |
Bearer と id_token の間は半角スペースで空けること。

<img width="767" alt="スクリーンショット 2017-03-28 15.46.38.png (109.4 kB)" src="https://img.esa.io/uploads/production/attachments/3044/2017/03/28/15045/bced42d0-f8c5-4736-b08f-0e4ae6fdc304.png">

トークンの検証が成功したことがわかる。

# まとめ

もう一度貼る
<img width="354" alt="スクリーンショット 2017-03-28 16.06.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/87900/c5056f22-28ad-a61e-b98c-e50a2cbc7474.png">

auth0を使い、webtask で実装したようなことを自鯖でアクセス時に毎回通過させるようにすれば、
ユーザ認証が簡単にできるようになる。他にも提供している機能として、[Get User Info ](https://auth0.com/docs/api/authentication#get-user-info)や、[Get Token Info](https://auth0.com/docs/api/authentication#get-token-info)を利用してユーザの情報をauth0に問い合わせて、取得出来たりもします。

※実際には[verify-access-token](https://auth0.com/docs/api-auth/tutorials/verify-access-token) に書いてありますが、デコードした中身を検証する必要があります。