LoginSignup
1
3

RailsとkeycloakでOIDC認証を試してみた

Posted at

株式会社 Vitalizeで webエンジニアをしている @nagaemon です。
現在は長野の支社にお世話になっており、現在はエンジニア + 地方創生事業に携わっています。
好きな言語はrubyです。

keycloakとは

Keycloakはオープンソースのアイデンティティ・アクセス管理ソフトウェアです
概要はこちらの記事がわかりやすいので、ご覧ください。
Keycloakとは

今回の目的

Qiitaでもkeycloak関連の記事はありますが、 Keycloak ✖️ Railsの記事がなかったので、自分の備忘録も兼ねて記事を書こうと思いました。

今回はkeycloakのOIDC(openIDconnect)を使って実際にrailsを用いてログイン機能が作れるのかどうかを試してみます。

サンプルファイル

開発環境

Keycloak

  • keycloak: 21.0.2
  • database: mysql:8.0.33

Rails

  • Rails 7.0.4

その他

  • Docker 24.0.2

Keycloak側の設定

Dockerでの立ち上げ方法

keycloakのGeting started内のDockerを参考にDocker-composeを作成。

docker-compose.yml
version: '3.8'

volumes:
  mysql_data:
      driver: local

services:
  mysql:
      image: mysql:8.0.33
      container_name: mysql
      volumes:
        - mysql_data:/var/lib/mysql
      environment:
        MYSQL_ROOT_PASSWORD: password
        MYSQL_DATABASE: keycloak
        MYSQL_USER: keycloak
        MYSQL_PASSWORD: password
      ports:
        - 3306:3306

  keycloak:
      image: quay.io/keycloak/keycloak:21.0.2
      container_name: keycloak
      environment:
        KEYCLOAK_ADMIN: admin
        KEYCLOAK_ADMIN_PASSWORD: admin
        KC_DB: mysql
        KC_DB_URL: jdbc:mysql://mysql:3306/keycloak
        KC_DB_URL_DATABASE: keycloak
        KC_DB_USERNAME: keycloak
        KC_DB_PASSWORD: password
        KC_HOSTNAME_STRICT: 'false'
        KC_HTTP_ENABLED: 'true'
        KC_HOSTNAME_STRICT_HTTPS: 'false'

      ports:
        - 8080:8080
      command:
        - "start"
        - "--auto-build"
shell
$ docker compose up

コマンド実行後にhttp://localhost:8080 にアクセス

keycloakの管理ページを確認できます。
スクリーンショット 2023-08-07 15.34.35.png

Administration Console にアクセスしましょう

ユーザ名とパスワードはdocker-composeファイルで指定していた ”admin" を使いましょう
スクリーンショット 2023-08-07 13.17.48.png

スクリーンショット 2023-08-07 15.35.51.png

レルム、クライアント、ユーザーの作成

レルム クライアント ユーザーはkeycloakのGeting started内のDockerでの立ち上げ方法に記載されてある方法を参考にしましょう。命名について、自分は今回下記のように作成しました。

  • realm: demo-realm
  • clients: demo-client
  • user: demo-user

加えて、今回はローカルで試すので
Valid redirect URIs は http://127.0.0.1:3000/*
Set Web origins は http://127.0.0.1:3000
に変更しておきましょう
スクリーンショット 2023-08-07 13.21.29.png

クライアント認証の設定

上記の設定に加えて、Rails等のサーバーサイドアプリケーションでの認証ですので。OIDCプロバイダ(keycloak)とのアクセス方法をConfidential Access Type (機密アクセスタイプ)に変更しましょう
具体的には、クライアント(サイドバー) → 設定タブ選択 → Capability config内のクライアント認証をONにしてもらえればOKです。

スクリーンショット 2023-08-07 14.08.32.png

その後、クレデンシャルタブ内のクライアント認証を「Client Id and Secret」を選択。
クライアントシークレットをどこかにメモしておきましょう。Railsの設定時に利用します。
スクリーンショット 2023-08-07 14.16.43.png

Rails側の設定

適当にディレクトリを作成後

shell
$ cd dir #=> 自分の好きなディレクトリ 
$ rails new .

Gemの利用

今回は

Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "3.2.2"

# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.6"

#---------省略---------
gem 'omniauth-keycloak'
gem 'omniauth-rails_csrf_protection'
# ↑↑上記を記入↑↑
group :development, :test do
  # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
  gem "debug", platforms: %i[ mri mingw x64_mingw ]
end
#---------省略---------

その後

shell
bundle install

omniauth自体の使い方はomniauthのgithubページに懇切丁寧に書かれています。

そちらを参考に少しいじります。

今回作ったappのディレクトリ/config/initializers/omniauth.rb
provider :keycloak_openid,
  'demo-client', #=> クライアント名
  'xxxxxxxxxxxxxxxx',#=> 事前にメモしておいたシークレットコード
  client_options: {base_url: '',#=> これをつけないと/authに飛んでしまうので、つける
  site: 'http://localhost:8080',#=> サイト
  realm: 'demo-realm'},#=> レルム名
  name: 'keycloak'
end
今回作ったappのディレクトリ/config/routes.rb
Rails.application.routes.draw do
  root "static_pages#top"
  get '/auth/:provider/callback', to: 'sessions#create'
  get '/login', to: 'sessions#new'
  get '/top', to: 'static_pages#top'
  get '/user', to: 'static_pages#user'
  delete '/logout', to: 'sessions#delete'
end

/auth/:provider/callback とエンドポイントを指定すると、omniauthがよしなにやってくれます。

sessions_controllerは下記のように作りました。

今回作ったappのディレクトリ/app/controllers/sessions_controller.rb
class SessionsController < ApplicationController
  protect_from_forgery
  def new
    render :new
  end

  def create
    user_info = request.env['omniauth.auth']
    uid = user_info&.uid
    email = user_info&.info&.email
    @user = User.find_or_create_by(email:, uid:)
    if @user.persisted?
      session[:user_id] = @user.id
      redirect_to user_path
    else
      redirect_to root_path
    end
  end

  def delete
    session[:user_id] = nil
    redirect_to  top_path
  end 
end

ビューはこのように加筆


<!DOCTYPE html>
<html>
# ------省略-------
<body>
    <main class="container mx-auto mt-28 px-5">
    <div class="bg-indigo-200">
        <% if user_signed_in? %>
          <%= button_to "ログアウト", logout_path, class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full", method: :delete %>
        <% else %>
          <%= button_to "keycloak_ログイン", '/auth/keycloak', class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full", data: {turbo: false} %>
        <% end %>
    </div>
      <%= yield %>
    </main>
  </body>

</html>

user_signed_in?などはヘルパーにしました。最後にサンプルをgithubにあげます。

設定が終わったら

shell
$ rails s

でサーバーを立ち上げましょう。

トップのログイン画面
スクリーンショット 2023-08-07 15.20.20.png

keycloak_ログインボタンを押すとkeycloakのログイン画面へリダイレクトされます。
スクリーンショット 2023-08-07 15.20.28.png

keycloakで作成したuserの名前とパスワードを入力するとログイン後のuserページに遷移できます。
スクリーンショット 2023-08-07 15.20.41.png

結構簡単に実装ができましたので、皆様も是非お試しください。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3