Skip to content

An OpenID Connect (oidc) Relying Party (RP) sample. Ruby 3 + Ruby on Rails 6.1. Tested Google and Yahoo JP.

Notifications You must be signed in to change notification settings

netsphere-labs/rails-openid-connect-rp-sample

Repository files navigation

An OpenID Connect Relying Party (RP) sample

OpenID Connect Provider (OP or IdP) 開発とデバッグのために、いろいろな投げつけをするサンプル。

See https://www.nslabs.jp/identity-samples.rhtml

OmniAuth を使っていたのを止め、実装しなおした。

Features

OpenID Connect Provider (OP) は Google と Yahoo JP, それに Rails OpenID Connect IdP AS

このサンプルは, Just-in-time User Provisioning (JIT Provisioning) の例にもなっている。あらかじめユーザ登録されていなくても、シングルサインオンで回ってくるユーザ情報で自サイトにも登録する。

(1) Authorization Code Flow with PKCE によるログイン

  • Google 実装すみ
  • Rails OpenID Connect IdP AS 実装すみ
  • Yahoo! JAPAN, Azure AD ●●未了

生の OAuth 2.0 の Implicit Flow を「認証」に使おうとすると、すごく巨大な穴が空く。OpenID Connect の Implicit Flow はその穴を塞いでいるので問題ない。しかし、巷の解説では混同しているものが非常に多い。

2024 年6月現在, OAuth 2.1 に向けた改訂作業が進んでいる。文言もだいぶ落ち着いてきて、もうすぐ最終化か? The OAuth 2.1 Authorization Framework Internet-Draft OAuth 2.1 は, 穴を塞ぐのではなく, 単に Implicit Flow を廃止にした。

今後は "public clients" も Authorization Code Flow でカバーしなければならず、Mobile & Desktop Apps では, nonce 必須, PKCE 必須。

(2) Implicit Flow によるログイン

OpenID Connect Implicit Client Implementer's Guide 1.0 を実装。

omniauth_openid_connect v0.4.0 は, response_type=id_token しかサポートしていない。これはアクセストークンが得られず、妥当ではない。

仕様では, IdP は, アクセストークンを発行しない場合に限って id_token レスポンスにユーザ情報を含めることになっている (Core 1.0: section 5.4) が、Yahoo! JAPAN ID 連携はこの仕様に適合せずユーザ情報を含めないので、動作しない。

ポータビリティのため, クライアントから id_token token を投げたうえで, UserInfo エンドポイントからユーザ情報を取得する。

Azure AD は、管理画面で Implicit Flow を有効にしている場合のみ。

(3) OpenID Connect RP-Initiated Logout 1.0 によるシングルログアウト (SLO)

IdP が end_session_endpoint をサポートしている場合、利用可能。 Azure AD v2 は、主に企業ユースで、シングルログアウトを必要とするユースケースがあるので、サポートしている。

シングルログアウトは, OpenID Connect (や他の OAuth2 上に作られたプロファイル) を使ったユースケースでは, 必要にならないことが多い。各サービス (Relying Party 側) がログアウトするときに Google とかもログアウトしたら、逆に困る。

How to run

  • Requirements

    • Ruby >= 3.0
    • Ruby on Rails v6.1
    • openid_connect

このサンプルでは認証フレームワークは Sorcery を使っているが、何でも構わない. OmniAuth はメジャーだが、屋上屋になるため、omniauth-openid-connect は使用しない。

  • Configuration
  1. config/database.yml.sampledatabase.yml にコピーし, 適宜修正.
  $ rake db:migrate
  1. config/auth/google.yml.sampleconfig/auth/yahoojp.yml.sample ファイルをコピーし, 適宜、編集してください。

client_id を設定してください。 Implicit Flow では client_secret を保存してはなりません。

  1. 実行!

Redirect URI は次のとおり;

  • http://localhost:3030/auth/google_codeflow/callback
  • http://localhost:3030/auth/google_implicit/callback

http://localhost:3030/auth/connect_op_sample/callback

Implicit Flow 実装上の注意

Authorization Code Flow は, クライアントが client secret を安全に保持できない状況では、使ってはならなかった。 Implicit Flow は, このような状況でも使えるように, client secret を必要としない (保存してはならない)。

"response_type" value は, id_token token とする。id_token は, Self-Issued OpenID Provider でのみ使われる。

Implicit Flow では, RP から OP に対する直接の問い合わせとレスポンスではなく, Webブラウザを介して id token と access token を得る。そのため、これらのトークンが正当なものか、必ず、検証しなければならない。

次のようなコードになる;

    def decode_token response, nonce
      id_token = OpenIDConnect::ResponseObject::IdToken.decode(
                        response['id_token'],
                        idp_public_keys)
      r = id_token.verify!({
                        :issuer => config.issuer,
                        :nonce => nonce,
                        :client_id => options[:client_id]})
    
      # さらに, access token を検証 (validation) しなければならない.
      jwt = JSON::JWT.decode response['id_token'], :skip_verification
      hash_length = jwt.alg[2, 3].to_i
      if id_token.at_hash !=
                left_half_hash_of(response['access_token'], hash_length)
        raise "invalid access_token!!"
      end

      return id_token, response['access_token']
    end

先行例

OpenID Foundationのガイドラインに沿ったRailsでのOIDC Implicit Flow実装

  • Ruby on Rails による実装.
  • OP (IdP) は Azure AD.
  • アクセストークンの検証が必要だが、そもそも取得していない?

Rails+omniauth-google-oauth2でGoogleログイン(devise無し)

  • omniauth-google-oauth2 のような IdP ごとに別パッケージを使うのではなく, OpenID Connect で統一的にシングルサインオンしたほうが、穴を作らない、と言う意味でもいい。
  • Devise を使わないのはいいが、この例は, 自作のログインコード、ログアウトコードが雑すぎて、これを参考にするのはむしろ有害。こういう雑なサンプルは、止めてほしい。

About

An OpenID Connect (oidc) Relying Party (RP) sample. Ruby 3 + Ruby on Rails 6.1. Tested Google and Yahoo JP.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published