Episodes

Resources

Download Source Code

Summary

# Terminal
touch .env
rails g controller sessions
rails g controller dashboards
rails g model user uid:string:index email

# .env
AUTH0_DOMAIN=XXX
AUTH0_CLIENT_ID=XXX
AUTH0_CLIENT_SECRET=XXX

# .gitignore
.env

# Gemfile
group :development, :test do
  gem 'dotenv-rails'
end

gem 'omniauth-auth0'
gem 'omniauth-rails_csrf_protection'

# config/initializers/auth0.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider(
    :auth0,
    ENV['AUTH0_CLIENT_ID'],
    ENV['AUTH0_CLIENT_SECRET'],
    ENV['AUTH0_DOMAIN'],
    callback_path: '/auth/auth0/callback',
    authorize_params: {
      scope: 'openid email profile'
    }
  )
end

# controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :authenticate_user!

  def current_user
    @current_user ||= User.find_by(id: session[:user])
  end
  helper_method :current_user

  def user_signed_in?
    session[:user].present? ? true : false
  end
  helper_method :user_signed_in?

  private

  def authenticate_user!
    return if user_signed_in?

    redirect_to root_path, alert: "You must be signed in to continue."
  end
end

# controllers/sessions_controller.rb
class SessionsController < ApplicationController
  skip_before_action :authenticate_user!, only: :create
  
  def create
    # session[:user] = request.env['omniauth.auth'].uid
    session[:user] = User.find_for_omniauth(request.env['omniauth.auth'])
    redirect_to root_path, notice: 'Signed In'
  end

  def destroy
    reset_session

    domain = ENV['AUTH0_DOMAIN']
    client_id = ENV['AUTH0_CLIENT_ID']
    request_params = {
      returnTo: root_url,
      client_id: client_id
    }
    url = URI::HTTPS.build(
      host: domain,
      path: '/v2/logout',
      query: to_query(request_params)
    )

    redirect_to url.to_s, notice: 'Signed Out'
  end

  private

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

# controllers/dashboards_controller.rb
class DashboardsController < ApplicationController
  def show
  end
end

# models/user.rb
class User < ApplicationRecord
  def self.find_for_omniauth(omniauth_params)
    user = find_or_initialize_by(uid: omniauth_params.uid)
    if user.new_record?
      user.email = omniauth_params.info.email
      user.save
    end
    user.id
  end
end

# config/routes.rb
Rails.application.routes.draw do
  resource :sessions, only: [:create, :destroy]
  resource :dashboard, only: :show
  get 'auth/auth0/callback' => 'sessions#create'

  root to: 'welcome#index'
end

# views/layouts/application.html.erb
<% if user_signed_in? %>
  <%= link_to "Dashboard", dashboard_path %> |
  <%= link_to 'Log Out', sessions_path, method: :delete %>
  Hello <%= current_user&.email %>
<% else %>
  <%= link_to 'Log In', 'auth/auth0', method: :post %>
<% end %>

# views/welcome/index.html.erb
<%= content_tag :div do %>
  <strong>Session:</strong> <%= session[:user] %>
<% end if user_signed_in? %>

# config/environments/development.rb
config.hosts = nil