RailsアプリにAuth0をサクッと導入する

# Auth0とは

![d227d2fd14274665.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/f076b7e8-0847-9235-e5c0-9a443945d1f6.jpeg)

>Auth0は誰でも簡単に導入できる認証・認可プラットフォームです。

*引用: [Auth0 -公式-](https://auth0.com/jp)*

Railsアプリであれば従来`devise`などのgemを使い認証機能を実装したり、`omniauth-twitter`や`omniauth-google`などのgemでソーシャルログイン機能を実装していたと思います。
そんな機能をローコードで実現できるのが`Auth0`です。
（※ 間違いあればご指摘ください🪓）

こんなログイン画面がノーコードで実現できちゃいます😎
（※ ログイン画面自体のコーディングは必要ないけど、各種設定のために多少のコードは書きます。）
![スクリーンショット 2021-07-26 0.46.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/77b7fcb9-65fb-6671-bd33-aa576f90d596.png)


# 作業環境

`MacBook Air (M1, 2020)`
`Ruby 3.0.2`
`Rails 6.1.4`

# 前提条件

既にRailsアプリが存在しているものとします。
(認証・認可機能は未実装)

ちなみに`Auth0`実装前のルーティングはたったこれだけ。

```ruby:config/routes.rb
Rails.application.routes.draw do
  root 'home#index'
  get 'dashboard', to: 'dashboard#show'
end
```

# 作業手順

## 1. Auth0アカウントを作成する

[Auth0 公式HP](https://auth0.com/jp) にアクセスし、スクショの通りに進めます。

![Auth1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/1ee18785-2659-3a61-d574-c8f69541d9cb.png)

![Auth2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/52075354-0c9b-df30-9385-f3b283d35b73.png)

![Auth4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/c3638b6d-6f75-abf2-6a7d-cd78db31f8aa.png)

![Auth5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/8d0e7276-4661-5dc7-75d4-09b1ff367f19.png)

無事にアカウント作成できました✨

## 2. Rails に Auth0 を導入する

### 2-1. Auth0 でアプリケーションの作成

次は、先ほどのダッシュボードから作業します。

![Auth6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/373a953e-3f5f-659b-1416-a7231d9c3557.png)

![Auth7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/4b9dc9de-6a3f-6759-fcaa-3bf93945108e.png)

![Auth8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/01457dfb-6240-859b-4dde-02eba6e75b6e.png)

![Auth9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/c0341f8f-c133-03ab-cb9e-4653277f21d0.png)

これで`Auth0`のアプリケーション作成は完了です✨

### 2-2. コールバックURL、ログアウトURLの設定

>- コールバックURLとは、Auth0がユーザーの認証後にリダイレクトする、あなたのアプリケーション内のURLです。
>- ログアウトURLとは、ユーザーが認可サーバーからログアウトした後に、Auth0が戻ることができるアプリケーション内のURLです。

*引用: [Auth0 -公式ドキュメント-](https://auth0.com/docs/quickstart/webapp/rails#configure-callback-urls)*

ここでは`Allowed Callback URLs`に`http://localhost:3000/auth/auth0/callback`、`Allowed Logout URLs`に`http://localhost:3000`と設定しておきましょう。

![Auth10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/f5e4354a-f32f-8ab3-2460-9a1a24ac32d8.png)

![Auth11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/1f02dd51-a318-6f8c-ebe9-7f70d61b78f5.png)

![Auth12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/89c93356-abed-b968-cbce-4bb08c479609.png)


### 2-3. Gemのインストール

お次はGemfileに`omniauth-auth0`と`omniauth-rails_csrf_protection`を追加します。

```diff:Gemfile
+ gem 'omniauth-auth0', '~> 3.0'
+ gem 'omniauth-rails_csrf_protection', '~> 1.0' # prevents forged authentication requests
```

```shell:terminal
% bundle install
```

### 2-4. Auth0設定ファイルの作成

`Auth0`の設定ファイルを作成します。
まずは`config`ディレクトリに`auth0.yml`という設定ファイルを作成します。

```shell:terminal
% touch config/auth0.yml
```

そして作成したファイルには下記のように記述します。

```yml:config/auth0.yml
development:
  auth0_domain: YOUR_DOMAIN
  auth0_client_id: YOUR_CLIENT_ID
  auth0_client_secret: <YOUR AUTH0 CLIENT SECRET>
```

:::note
`YOUR_DOMAIN`, `YOUR_CLIENT_ID`, `YOUR AUTH0 CLIENT SECRET`は下記に記載してあります*
:::
:::note alert
<font color="red">**ただし、このファイルはシークレットキーなどの秘匿情報が記載されているため、Git管理しないよう取扱い注意☝️**</font>
:::

![Auth12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/34857412-1a38-c63e-ba03-c5ac4716ff3a.png)

次に`config/initializers`ディレクトリに`auth0.rb`という設定ファイルを作成します。
※ こちらは`auth0.yml`じゃなくて`auth0.rb`、拡張子は`rb`なのでお間違い無く。

```shell:terminal
% touch config/initializers/auth0.rb
```

作成したファイルには下記のように記述します。

```ruby:config/initializers/auth0.rb
AUTH0_CONFIG = Rails.application.config_for(:auth0)

Rails.application.config.middleware.use OmniAuth::Builder do
  provider(
    :auth0,
    AUTH0_CONFIG['auth0_client_id'],
    AUTH0_CONFIG['auth0_client_secret'],
    AUTH0_CONFIG['auth0_domain'],
    callback_path: '/auth/auth0/callback',
    authorize_params: {
      scope: 'openid profile'
    }
  )
end
```

### 2-5. Auth0用コントローラーの作成

次にAuth0用のコントローラーを作成します。
下記コマンドを実行しましょう。

```shell:terminal
% rails generate controller auth0 callback failure logout --skip-assets --skip-helper --skip-routes --skip-template-engine
```

そしてコントローラーの中身は下記のように編集します。

```ruby:app/controllers/auth0_controller.rb
class Auth0Controller < ApplicationController
  def callback
    auth_info = request.env['omniauth.auth']
    session[:userinfo] = auth_info['extra']['raw_info']

    redirect_to '/dashboard'
  end

  def failure
    @error_msg = request.params['message']
  end

  def logout
    reset_session
    redirect_to logout_url
  end

  private

  AUTH0_CONFIG = Rails.application.config_for(:auth0)

  def logout_url
    request_params = {
      returnTo: root_url,
      client_id: AUTH0_CONFIG['auth0_client_id']
    }

    URI::HTTPS.build(host: AUTH0_CONFIG['auth0_domain'], path: '/v2/logout', query: to_query(request_params)).to_s
  end

  def to_query(hash)
    hash.map { |k, v| "#{k}=#{CGI.escape(v)}" unless v.nil? }.reject(&:nil?).join('&')
  end
end
```

次はルーティングの設定です。
下記の3つを追加します。

```diff:config/routes.rb
Rails.application.routes.draw do
   ...
+  get '/auth/auth0/callback' => 'auth0#callback'
+  get '/auth/failure' => 'auth0#failure'
+  get '/auth/logout' => 'auth0#logout'
end
```

### 2-6. セキュアモジュールの作成

次はセキュアモジュールを作成します。ここでいうセキュアモジュールとは、`devise`でいう`authenticate_user!`メソッドに当たります。つまるところログイン必須機能です。

`app/controllers/concerns`ディレクトリに`secured.rb`を作成します。

```shell:terminal
% touch app/controllers/concerns/secured.rb
```

中身は下記の通りにしてください。

```ruby:app/controllers/concerns/secured.rb
module Secured
  extend ActiveSupport::Concern

  included do
    before_action :logged_in_using_omniauth?
  end

  def logged_in_using_omniauth?
    redirect_to '/' unless session[:userinfo].present?
  end
end
```

これで`Auth0`の導入は完了です🎉
お疲れ様でした！

## 3. Auth0 を配置

さて、ようやく`Auth0`を配置するフェーズに来ましたね😎
やるべきことはこれだけ。

1. ログイン・ログアウトボタンの設置
1. ログイン必須アクションにセキュアモジュールを導入
1. ログイン後のビュー修正

では順を追って進めていきましょう。

### 3-1. ログイン・ログアウトボタンの設置

今回は単なる説明なので、どちらもホーム画面に設置します。

```erb:app/views/home/index.html.erb
<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>

<%= button_to 'Login', 'auth/auth0', method: :post %>
<%= button_to 'Logout', 'auth/logout', method: :get %>
```

### 3-2. ログイン必須アクションにセキュアモジュールを導入

このアプリにはホーム画面とダッシュボードしか用意していません。
今回は仮に、ホーム画面はログインしていなくてもアクセスできるものとし、ダッシュボードはログインしていないとアクセスできないものとします。

なのでセキュアモジュールを導入するのはダッシュボード閲覧のコントローラー#アクションですね。
ダッシュボードではログインユーザーの情報を表示したいので、ログインユーザーデータを持ったインスタンス変数`@user`を定義しましょう。

```ruby:app/controllers/dashboard_controller.rb
class DashboardController < ApplicationController
  include Secured # セキュアモジュールを導入

  def show
    @user = session[:userinfo]
  end
end
```

### 3-3. ログイン後のビュー修正

ここではシンプルにログインユーザーの名前を表示することにします。

```erb:app/views/dashboard/show.html.erb
<h1>Dashboard#show</h1>
<p>Find me in app/views/dashboard/show.html.erb</p>

<div>
  <p>User Profile: <%= @user['name'] %></p>
</div>
```

これで準備完了🙆‍♂️

# 4. Auth0 を実感

いよいよ`Auth0`を実感する瞬間がやってまいりました！
`http://localhost.3000`にアクセスし、ログインボタンを押してください。
見事なまでのログイン画面が表示され、ログイン後はユーザー名が表示されるはずです✨

![Auth14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/5a05f59a-75a7-7d54-6fbb-f345596213b3.png)

![Auth15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/aae5ae6f-221f-50ae-98cc-4dec986dbd92.png)

![Auth16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89868/b7aa736b-e99d-db63-f7a9-c624b7078153.png)

できた🎉

# 5. おわりに

いかがでしたか？
かなり簡単に`Auth0`を導入できたのではないでしょうか😊

このままでは肝心のRailsアプリケーションにユーザー情報を持っていなかったり、Google以外のソーシャルログインができなかったりと修正したい部分は多々ありますが、最低限の流れを掴んでいただけたら幸いです。

自分自身、`Auth0`を導入するのが今回初めてだったので、これからも気付きがあれば随時追記していこうと思います。