【Rails API 入門】devise-token-auth

# はじめに
### devise-token-auth とは？
Railsにおける**トークン認証**を実現するgemです。

この`devise-token-auth`を用いることで、新規登録、ログイン・ログアウトなどはもちろんのこと、アプリ各種操作を行う時に`header`情報にユーザーの認証情報（トークン）を載せてバックエンド側（RailsのAPI側など）に送ることで、毎回の処理を安全に実行することができます。

- [GitHubリンク](https://github.com/lynndylanhurley/devise_token_auth)
- [詳細解説ページ](https://devise-token-auth.gitbook.io/devise-token-auth/)

そこで今回は、**RailsでAPI提供を行う際の devise-token-auth の使い方**について解説します。

### トークン認証 とは？ 
簡単に言うと、ログイン・ログアウト、新規登録などのユーザー認証を行う方法の1つで、トークンと呼ばれるしるし（トークンの英語訳）のようなものを利用して認証を行います。

トークン認証の他に、cookiesと呼ばれるものを使ったsession認証が有名ですが、**RailsをAPI提供として利用する**場合、アプリケーションの動作環境がネイティブアプリ（Mac, Windows, android, iOSなど）になることがあります。
これらネイティブアプリでは、cookiesを保存できないことがある（つまり、session認証ができない）ことがあるので、このトークン認証が注目されています（トークン認証とsession認証の違いについて詳しく知りたい方は[こちら](https://magazine.techcareer.jp/technology/skill/11273/)をご覧下さい）。

# 初期設定
まずは、APIモードでRailsアプリとデータベースを作成して下さい。

```rb
rails new [アプリ名] --api -d [使用するDB] # -d 以降は省略しても構いません
```

```rb
rails db:create
```

それでは、`devise_token_auth`をGemfileに追加しましょう。

このタイミングで`devise`、必要に応じて`rack-cors`gemを一緒にインストールして下さい。
`devise`は`devise_token_auth`の細かいところをフォローしてくれ、`rack-cors`はフロントエンドがVue、バックエンドでRailsのAPI提供を行うといった場合に、URL（詳しくはorigin）のアクセスが重複することを許可してくれます。

```rb
  gem "devise"
  gem "devise_token_auth"
  gem "rack-cors" # Railsアプリインストール時にコメントアウトされていると思います。
```
次に、`devise`、`devise_token_auth`の順にインストールを行いましょう（DBを作成していない場合や、順番を間違えるとエラーが発生するので注意）。

```rb
rails g devise:install
```

```rb
rails g devise_token_auth:install User auth
```

これで準備は完了です！

次からは実際に、認証機能を実装していきましょう！

# 認証機能実装
APIのバージョンを管理をする（v1、v2など）ことが多いと思いますので、その想定で実装していきます。

まずは、`devise_token_auth`を用いた認証を行うコントローラーを作成します。

```rb
rails g controller v1/auth/registrations
```

すると、`app/controllers/v1/auth/registrations_controller.rb`が作成されるので、それを以下内容に修正して下さい。

```rb:v1/auth/registrations_controller.rb
class V1::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
end
```

これは何をしているのか？と言いますと、`devise_token_auth`gemであらかじめ用意されている認証用のコントローラーを、作成した`registrations_controller`に継承しています。

継承したコントローラーを使用し、次の内容のルーティングを設定することで、使用するアプリの認証機能を実現することが可能となります！

```rb:config/routes.rb
  namespace :v1 do
    mount_devise_token_auth_for "User", at: "auth"
  end
```

また、作成された`User`モデルの`:trackable`をコメントアウトするか、削除して下さい（ログイン時にエラーが発生します）。

```rb:user.rb
class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :trackable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  include DeviseTokenAuth::Concerns::User
end
```

# 使い方

[こちら（以下）](https://devise-token-auth.gitbook.io/devise-token-auth/usage)から、どのようなHTTPリクエストで各種ユーザー認証機能を使うことができるのかを確認できます。

右側の`purpose`に、それぞれ必要となるパラメータが記載されてあるため、それらパラメータをリクエスト時に渡す必要があります。

具体的な内容は、次の**動作確認**セクションで説明しますね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/a1b1de93-4587-a452-6c93-b730431dd7df.png)

# 動作確認

今回は簡易的な動作確認として[Advanced Rest client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo/details?hl=ja-JP)を使用して動作確認を行います（RailsのRSpecでテストを実装することがベストな確認方法です）。

Advanced Rest client とは、HTTPリクエストの送信、レスポンスの確認が可能なchromeの拡張機能です。

これを使い、それぞれのユーザー認証機能に必要なパラメータをJSONとして送信します。

実際のアプリでは、フロントエンド側からこれらのパラメータをバックエンド側に渡し、当記事内容で実装する`devise_token_auth`を用いることでバックエンド側で認証処理が行われるため、ログインやログアウトなどが実現されるようになるのです！

### 新規登録

[こちら](https://devise-token-auth.gitbook.io/devise-token-auth/usage)の通り、新規登録で入力するパスは`[ドメイン]/v1/auth`、HTTPメソッドは`POST`です。

`Body`欄から、新規登録するユーザー情報として必要な

- email
- password

をJSON形式で入力し、右上の**SEND**を押してください。HTTPリクエストが送られます。
（railsをサーバーで起動するのを忘れないで下さいね！）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/5fe2f210-48bf-b401-3e00-f2b6981a1d14.png)

すると、真ん中あたりに`200 OK`というリクエストが成功したという表示がでます！

`Headers`欄を見ると、レスポンスとして`provider`や`uid`などの値が返ってきていることが確認できましたね！

新規登録の成功です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/195b2066-9d23-281c-b5bf-1d92f500d0aa.png)

### ログイン

入力するパスは`[ドメイン]/v1/auth/sign_in`、HTTPメソッドは`POST`です。

`Body`欄からログインに必要な

- email
- password

をJSON形式で入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/4dcd1748-7136-d6dd-2d96-f44a725d9d57.png)

これも同様に成功し、以下のような結果が返ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/6845041f-11a1-9fbf-90fd-b1353fcf2727.png)

### サインアウト

パスは`[ドメイン]/v1/auth/sign_out`、HTTPメソッドは`DELETE`。必要なパラメータは、次の3つです。

- uid
- access-token
- client

先程解説したログイン処理の後、`Response headers`欄に、今回のサインアウトで必要なパラメータの`uid`、`access-token`、`client`が記載されてあります！

それらを参考に入力し、SENDするとサインアウトが実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/5316b695-fd0e-21a6-d7dc-d6db30a386be.png)

こちらが成功画面。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/10640e6b-dad6-6cd3-f99b-a96119e19966.png)

### アカウントの削除

もう慣れてきましたね！

パスは`[ドメイン]/v1/auth/`、HTTPメソッドは`DELETE`です。

- uid
- access-token
- client

を入力して下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/b836c258-b0f3-e752-ad2d-a925970b3d4e.png)

成功画面。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515882/d2b59a22-ee9a-2af4-2c8a-08bfe4485579.png)


# 参考
- [Cookie(Session)での認証と Token での認証の違いについて](https://magazine.techcareer.jp/technology/skill/11273/)