Omniauth GitHub on Rails
Tags: ruby, rails, omniauth
Published: 2020-05-05 17:10:04

---
title: Omniauth GitHub on Rails
published: true
tags: Ruby,Rails,Omniauth
---

`omniauth-github`でRuby on Railsのログイン機構を作るときに何度も検索したりすることがあるので、ざっくりやりかたをまとめました。

## 作業リポジトリ

{% github YutaGoto/rails_github_auth %}

## 環境

- Ruby: 2.6.5
- Rails: 6.0.2.2
- omniauth-github: 1.4.0

## 使用したGem

{% github omniauth/omniauth-github %}

## ざっくり手順

### `Gemfile` に書き加える

```Gemfile
gem 'omniauth-github'
```

bundle installする

### GitHub Applicationを作る

https://github.com/settings/apps

上記リンクにアクセスして新規で作成する。

![ぎてゅｂ](https://dev-to-uploads.s3.amazonaws.com/i/z04n40v7u9wegdda69lk.png)

ざっくり編集する

開発用で設定するときは Homepage URLを `http://localhost:3000`、User authorization callback URLを `http://localhost:3000/auth/github/callback` にする。

Permissionの設定はユーザ登録だけであれば、`User permissions`のEmail AddressesをRead-onlyにする

![ぎっとはぶ](https://dev-to-uploads.s3.amazonaws.com/i/sde3arhxh9gwczmu534v.png)

作成し終えたら Client IDとClient secretを控える

### 環境変数にセットする

```sh
EDITOR="vim" bin/rails credentials:edit
```

```yml
github_omniauth:
  client_id: hoge
  client_secret: hogehoge
```

yaml形式で設定する。実際に反映されるているか確認するときは、 `rails console` を使用する

```sh
$ rails c
Loading development environment (Rails 6.0.2.2)
irb(main):001:0> Rails.application.credentials.github_omniauth
=> {:client_id=>"hoge", :client_secret=>"hogehoge"}
```

###  Userモデルを作る

```sh
rails g model user name:string provider:string uid:text oauth_token:string
rails db:create
rails db:migrate
```

```rb
# app/models/user.rb
class User < ApplicationRecord
  def self.find_or_create_with_omniauth!(auth)
    user = find_by(uid: auth['uid'])
    return user if user.present?
    create! do |user|
      user.provider = auth['provider']
      user.uid = auth['uid']
      user.name = auth['info']['nickname']
      user.oauth_token = auth['credentials']['token']
    end
  end
end
```

### Routingを設定する

```config/routes.rb
# config/routes.rb
Rails.application.routes.draw do
  get 'auth/github/callback', to: 'sessions#callback'
  get '/sign_out', to: 'sessions#destroy'

  root 'homes#top'
end
```

### SessionsControllerを作る

```sh
rails g controller sessions
```

```rb
# app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  def callback
    user = User.find_or_create_with_omniauth!(request.env['omniauth.auth'])
    session[:user_id] = user.id
    redirect_to root_path
  end

  def destroy
    reset_session # セッションをリセットする
    redirect_to root_path
  end
end
```

### HelperMethodを作る

```rb
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  helper_method :current_user, :logged_in?

  private

  def current_user
    return unless session[:user_id]
    @current_user ||= User.find(session[:user_id])
  end

  def logged_in?
    !!session[:user_id]
  end

  def authenticate
    return if logged_in?
    redirect_to root_path, alert: 'ログインしてください'
  end
end
```

### Viewを作る

```erb
<%# app/views/homes/top.html.erb %>
<% if logged_in? %>
  <%= link_to 'Sign out', '/sign_out' %>
  <ul>
    <li>ID: <%= current_user.id %></li>
    <li>NAME: <%= current_user.name %></li>
    <li>PROVIDER: <%= current_user.provider %></li>
  </ul>
<% else %>
  <%= link_to 'Githubアカウントでサインイン', '/auth/github' %>
<% end %>
```

### Omniauthの設定ファイルを作成する

```sh
touch config/initializers/omniauth.rb
```

```rb
# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :developer unless Rails.env.production?
  provider :github, Rails.application.credentials.github_omniauth[:client_id], Rails.application.credentials.github_omniauth[:client_secret], scope: "user"
end
```

### 実際に確認する

```sh
rails s
```

#### サインイン前

![ro-karu](https://dev-to-uploads.s3.amazonaws.com/i/ftj9tqcliuocfgu9ayq3.png)

#### サインイン後

![login](https://dev-to-uploads.s3.amazonaws.com/i/d908c53vo5comkin8154.png)

### テストコード

途中

https://github.com/omniauth/omniauth/wiki/Integration-Testing

これを参考にすすめると良さそう