RailsでつくるOpenID Provider 入門
Rails でつくる OpenID Provider 入門
はじめに
こんにちは、Rails エンジニアの 安田 です。業務で OpenID Provider(OP) をゼロから試作する機会がありました。ただ、当初は OAuth 2.0 や OpenID Connect(OIDC) に触れたことがなく、その概念の多さに圧倒されました。
そこで、実際に手元で動く プロトタイプ版 OP を構築してみると、特に「認可コードフロー」や「ID トークン」の流れをスムーズに理解できました。本記事では、その体験を基に Rails で “理解用プロトタイプ” を構築する手順を紹介します。
⚠️ 注意事項
本稿は学習用に 最小限の実装 を示します。秘密鍵管理や HTTPS、PKCE 強制など、実運用で必須となるセキュリティ対策は割愛しています。実環境に導入する際は必ず最新のベストプラクティスを参照してください。
1. 概念整理
1‑1 OpenID Connect(OIDC)とは?
- OAuth 2.0 を拡張し、ユーザーの 認可(リソースアクセス可否)に加えて 認証(誰がログインしたか)の結果を ID トークン として提供する仕様。
1‑2 OpenID Provider(OP)
- アクセストークンや ID トークンを発行するサーバー。今回の記事で構築する対象です。
1‑3 Relying Party(RP)
- OP に認可/認証を委譲し、返されたトークンを用いてサービスを提供するクライアント。
2. 実装
2‑1 動作環境 & 依存 Gem
ソフトウェア / Gem | バージョン | 役割 |
---|---|---|
Ruby | 3.4.3 | |
Rails | 8.0.2 | Web アプリケーションフレームワーク |
devise | 4.9.4 | ユーザー認証(ログイン) |
doorkeeper | 5.8.2 | OAuth 2.0 Provider |
doorkeeper‑openid_connect | 1.8.11 | OIDC 拡張 |
2‑2 セットアップ手順
Step 1 devise 導入(ユーザー認証)
OIDCのユーザー認証用にRailsではよく使われている、deviseを使います。
rails generate devise:install # 初期設定
rails generate devise User # User モデル生成
rails db:migrate
Step 2 Doorkeeper 導入(OAuth 2.0 サーバー)
Oauth2 Provider として、Doorkeeperを導入します。他にも候補はありましたが、ドキュメントが一番充実していたので採用しています。
rails generate doorkeeper:install
rails generate doorkeeper:migration
rails db:migrate
Step 3 doorkeeper‑openid_connect 導入(OIDC 拡張)
OpenID Provider としてDoorkeeper を使うために、doorkeeper-openid_connectを使います。
rails generate doorkeeper:openid_connect:install
rails generate doorkeeper:openid_connect:migration
rails db:migrate
署名鍵を固定で用意
署名鍵を設定します。今回はID トークンの検証はスコープ外としているので、適当な固定値が入っていれば問題ありません。
# サンプル: 2048bit RSA 鍵を生成
openssl genrsa -out config/jwt_rsa.pem 2048
# config/initializers/doorkeeper_openid_connect.rb
Doorkeeper::OpenidConnect.configure do
signing_key File.read(Rails.root.join("config/jwt_rsa.pem"))
end
Step 4 devise と Doorkeeper の連携
DoorKeepr のモデルを Devise の Userモデルと紐付けます。
# app/models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :access_grants,
class_name: 'Doorkeeper::AccessGrant',
foreign_key: :resource_owner_id,
dependent: :delete_all
has_many :access_tokens,
class_name: 'Doorkeeper::AccessToken',
foreign_key: :resource_owner_id,
dependent: :delete_all
end
Doorkeeperのユーザー認証にdeviseを使うようにします。
認可リクエストが来たら
未ログインならログイン画面へリダイレクト
ログイン済みならそのまま同意画面へ遷移
という流れになります。
# config/initializers/doorkeeper.rb
resource_owner_authenticator do
current_user || warden.authenticate!(scope: :user)
end
Step 5 OIDC 用スコープ
OIDC用のスコープを追加します。認証時にscopeとしてopenidを受け取れるようになり、OIDCが使えるようになります。
# config/initializers/doorkeeper.rb
Doorkeeper.configure do
default_scopes :openid # OIDC は必須
end
Step 6 保護リソース(API) の作成
テスト用のエンドポイントを作成します。OIDCで得たアクセストークンがあるとアクセスできるエンドポイントです。
# app/controllers/credentials_controller.rb
class CredentialsController < ApplicationController
before_action :doorkeeper_authorize!
def me
render json: current_resource_owner
end
private
def current_resource_owner
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end
end
Step 7 ルーティング
Doorkeeper, devise のエンドポイントを追加します。
# config/routes.rb
Rails.application.routes.draw do
use_doorkeeper
use_doorkeeper_openid_connect
devise_for :users
get :me, to: 'credentials#me'
end
Step 8 クライアントアプリ登録
Rails console で実行して、クライアントを登録しておきます。
Doorkeeper::Application.create!(
name: 'test_app',
uid: 'test_uid',
redirect_uri: 'http://localhost:4000/callback', # ローカル開発用
scopes: 'openid',
confidential: false
)
3. 動作確認
以下では 認可コードフロー を試します。ブラウザ / cURL の 2 ステップで完了します。
3‑1 認可コード取得
ブラウザで以下にアクセスし、ログイン→同意するとリダイレクト先 URI に code=
が付与されます。
http://localhost:3000/oauth/authorize?response_type=code&client_id=test_uid&redirect_uri=http://localhost:4000/callback&scope=openid
3‑2 アクセストークン & ID トークン取得
curl -X POST http://localhost:3000/oauth/token \
-F grant_type=authorization_code \
-F client_id=test_uid \
-F code=<ブラウザで得た code> \
-F redirect_uri=http://localhost:4000/callback
レスポンスとして、アクセストークン、ID トークンが得られます。アクセストークンの有効期限はdoorkeeper のデフォルト値が設定されています。
{
"access_token": "kiYNazG5XWBcLv...",
"token_type": "Bearer",
"expires_in": 7200,
"scope": "openid",
"id_token": "eyJ0eXAiOiJKV1QiLCJraWQiOiJC..."
}
ここでは、ID トークンの検証はしません
3‑4 保護リソースへアクセス
取得したアクセストークンで保護リソースにアクセスします。
curl -H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
http://localhost:3000/me
このエンドポイントでは、ユーザー情報を取得できれば成功です。
{
"id": 1,
"email": "user1@example.com",
"created_at": "2025-02-27T05:37:38.177Z",
"updated_at": "2025-02-27T05:37:38.177Z"
}
これで OP の動作を確認できました。
4. 振り返り
OIDC は OAuth 2.0 に「誰がログインしているか」という認証機能を加えた拡張仕様で、ID トークンを介してユーザー情報を安全に伝達できます。Rails では devise(ログイン)、doorkeeper(OAuth 2.0)、doorkeeper-openid_connect(OIDC)の 3 つの Gem だけで OP を構築できます。ただし、運用する際は鍵管理や HTTPS の導入、PKCE の必須化、トークン検証といったセキュリティ対策を必ず入れましょう。
最後までお読みいただきありがとうございました!
We are hiring!
ブルーモでは、次世代の金融プロダクトを一緒に開発する仲間を募集中です。興味のある方はぜひ採用ページもご覧ください。

ブルーモ証券株式会社のプロダクトチームブログです。「投資をみんなのものに」をミッションに、ポートフォリオをコピーして簡単に米国株・ETFで資産運用できるアプリ"ブルーモ"を提供しています。 各種エンジニア・デザイナー・PdMポジションを積極採用中です! careers.bloomo.co.jp/
Discussion