Railsで OpenID Connect(OIDC) に準拠したクライアント実装

RailsでOpenID Connect(OIDC) に準拠したクライアント実装の備忘録です。

OpenID Connect

OpenID Connect(OIDC)は、ユーザーの同意に基づいてサービス間で ID 情報をやり取りするための標準仕様です。OAuth 2.0 プロトコルを使用して構築されたオープン・スタンダードです。

【情シス基礎知識】OpenID Connectとは? 第一回 認証基盤のこれからを支えるOpenID Connect | オブジェクトの広場

使用ライブラリ

OpenID Foundation の、各言語の関連ライブラリ一覧 でRubyのライブラリが紹介されています。

Certified Relying Party Libraries > Ruby にて

openid_connect rubygem v1.0.3

  • RP sample implementation in Ruby on Rails using ‘openid_connect’ gem
  • Target Environment: Ruby for any Rack-based applications (including Ruby on Rails)
  • License: MIT
  • Certified By: Nov Matake
  • Conformance Profiles: Basic RP
OpenID Foundation

使用方法

シンプルなサンプル

https://github.com/nov/openid_connect_sample2/blob/master/sample_rp.rb より

require 'openid_connect'

OpenIDConnect.debug!

client = OpenIDConnect::Client.new(
  identifier: 'rp.dev',
  secret: '42347d901a6686a533067285ed13ee1b475121a6ece10446299f4be62e4e4bfc',
  redirect_uri: 'http://rp.dev/providers/3/open_id',
  host: 'op2.dev',
  scheme: 'http',
  authorization_endpoint: '/authorizations/new',
  token_endpoint: '/tokens',
  userinfo_endpoint: '/user_info'
)

redirect_uri = client.authorization_uri(
  scope: [:email, :profile],
  state: SecureRandom.hex(8),
  nonce: SecureRandom.hex(8)
)

puts redirect_uri
`open "#{redirect_uri}"`

print 'code: ' and STDOUT.flush
code = gets.chop

client.authorization_code = code
client.access_token!

サンプル(Controller)

コントローラでアクセストークンを受け取り表示するまでのサンプルです。

class OpenConnectController
  def login
    render inline: "[<a href='<%= open_connect_auth_url %>'>OpenID連携</a>]"
  end

  def auth
    client = init_client
    params = {
      scope: [:openid, :user_info],
      state: SecureRandom.hex(8),
      nonce: SecureRandom.hex(16)
    }
    redirect_uri = client.authorization_uri(params)
    session[:open_connect_auth] = params

    redirect_to redirect_uri, status: 302
  end

  def authorize
    code = params[:code]
    state = params[:state]
    render plain: 'ERROR: state mismatch' and return unless session[:open_connect_auth]['state'] == state

    client = init_client
    client.authorization_code = code
    access_token = client.access_token!

    p access_token
    p access_token.id_token

    render json: {
      success: true,
      id_token: access_token.id_token
    }
  end

  private

  def init_client
    @client ||= OpenIDConnect::Client.new(
      identifier: 'rp.dev',
      secret: '42347d901a6686a533067285ed13ee1b475121a6ece10446299f4be62e4e4bfc',
      redirect_uri: 'https://xxxxxxxx.xxx/open_connect/authorize',
      host: 'op2.dev',
      scheme: 'https',
      authorization_endpoint: '/oauth2/auth',
      token_endpoint: '/oauth2/token'
    )
  end
end

参考

Ruby OpenID Connect example Rubyで理解するOpenID Connect OpenID Foundationのガイドラインに沿ったRailsでのOIDC Implicit Flow実装 – Qiita

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA