Conversation
| <%= hidden_field_tag :response_type, @pre_auth.response_type %> | ||
| <%= hidden_field_tag :response_mode, @pre_auth.response_mode %> | ||
| <%= hidden_field_tag :scope, @pre_auth.scope %> | ||
| <%= hidden_field_tag :nonce, @pre_auth.nonce %> |
There was a problem hiding this comment.
| has_many :ownership_calls, -> { opened }, dependent: :destroy, inverse_of: :user | ||
| has_many :ownership_requests, -> { opened }, dependent: :destroy, inverse_of: :user | ||
|
|
||
| has_many :access_grants, class_name: 'Doorkeeper::AccessGrant', foreign_key: :resource_owner_id, dependent: :destroy |
| # Example implementation: | ||
| # User.find_by(id: session[:user_id]) || redirect_to(new_user_session_url) | ||
|
|
||
| user = User.last |
There was a problem hiding this comment.
Terrible hack! I'm not familiar enough with rubygems.org and its use of Clearance to find the currently authenticated user.
|
|
||
| Doorkeeper::OpenidConnect.configure do | ||
| issuer do |resource_owner, application| | ||
| "http://localhost:3000/oauth" |
There was a problem hiding this comment.
TODO compare this with other OIDC provider issuer urls.
| "http://localhost:3000/oauth" | ||
| end | ||
|
|
||
| signing_key File.read("private_id_token_key.pem") |
There was a problem hiding this comment.
| # or if you need pairwise subject identifier, implement like below: | ||
| # Digest::SHA256.hexdigest("#{resource_owner.id}#{URI.parse(application.redirect_uri).host}#{'your_secret_salt'}") | ||
| # profile_path(resource_owner.display_id) | ||
| "http://localhost:3000/profiles/#{resource_owner.display_id}" |
There was a problem hiding this comment.
This sets the sub claim in the ID token. Fulcio may prefer to receive the subject alternative name URI from another claim.
| @@ -1,4 +1,6 @@ | |||
| Rails.application.routes.draw do | |||
| use_doorkeeper_openid_connect | |||
There was a problem hiding this comment.
We may not need all routes and actions. There is room for improvement here.
| @@ -0,0 +1,8 @@ | |||
| # frozen_string_literal: true | |||
|
|
|||
| class EnablePkce < ActiveRecord::Migration[6.1] | |||
There was a problem hiding this comment.
There was a problem hiding this comment.
On further reflection, PKCE likely will not be needed for requests coming from sigstore. It is a server-side application, and can be trusted with a client secret.
Work in progress
A proof of concept branch that adds enough support for OAuth and OpenID Connect to work with sigstore's auth and Fulcio components (I think).
Note that I manually registered an application client using the Rails console. Imagine that sigstore would be registered as a client capable of maintaining a client secret.
Sending a request for an authorization code:
Edit: ignore the PKCE fields in my examples and in the code. I don't think that will be needed, given that sigstore is a server application that can maintain a client_secret.
Normally we would be redirected to the sign in page as needed. We would need to grant
MyApptheopenidscope, unless we decide to auto-grant. An explicit grant step seems a bit irrelevant in the sigstore usecase, IMO.The server redirects the browser to the redirect_uri with the auth code and ephemeral state
The client then POSTs to the token endpoint, supplying the auth code along with other expected params:
The client receives this response
{ "access_token": "PqkQyLLT6yab8hzi2fuu8XbEUmJ5KRUPZg6K7Mipuys", "token_type": "Bearer", "expires_in": 7200, "scope": "openid", "created_at": 1644008140, "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ii1hZFpnLXJKVFFBSlRXYmhfUjlBci1WUGRNUjNSejZ0VHQ4Z045ek11M1kifQ.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAvb2F1dGgiLCJzdWIiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAvcHJvZmlsZXMvTGFSb2NhaWxsZSIsImF1ZCI6Ii1sRkdsdk9fSTZLVzdrdEpmUlVKSDBqR1AyaVdzMTc0bG94VE9ydG1PZzAiLCJleHAiOjE2NDQwMDgyNjAsImlhdCI6MTY0NDAwODE0MCwibm9uY2UiOiI5MWZhMzE3NDg0ZTE3MzkxN2UzZGQ5MjRlOTY1ZWVmMSJ9.TFjov2mOpurmP7-7hi7Wxy-ZVtGoagTNOSvk-KMywglZsOIkR7ZK9VDml_2qABfE8U4OwttmHhSkLFW9gGyV2P6c18xpJgpf8-cbAk95QfFHpmBfngegwvtwZi8USNx1IoKVH2GonYpZCCgn2WswJSohMfnKJTgQvYhDqiG7DXHOQex0Rd8iAtWCNA4ScPt0fmoqfRXn-HdPOU0_KfKu4_-9Z74MlkPHi62gdzxtpOLL927tmSePGzb9n371kLL8i7ZlXEEMOpbeKGfjlbQE4HisWWxZ0nxD-4cCWW47xV-y_4yCTlAE4mo4oseo52ux_6AUEtHPp6DflSSImDua8w" }The decoded id_token contains the rubygems.org account's profile URI:
Sample response from http://localhost:3000/.well-known/openid-configuration
{ "issuer": {}, "authorization_endpoint": "http://localhost:3000/oauth/authorize", "token_endpoint": "http://localhost:3000/oauth/token", "revocation_endpoint": "http://localhost:3000/oauth/revoke", "introspection_endpoint": "http://localhost:3000/oauth/introspect", "userinfo_endpoint": "http://localhost:3000/oauth/userinfo", "jwks_uri": "http://localhost:3000/oauth/discovery/keys", "scopes_supported": [], "response_types_supported": [ "code", "token", "id_token", "id_token token" ], "response_modes_supported": [ "query", "fragment", "form_post" ], "grant_types_supported": [ "authorization_code", "implicit_oidc" ], "token_endpoint_auth_methods_supported": [ "client_secret_basic", "client_secret_post" ], "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "RS256" ], "claim_types_supported": [ "normal" ], "claims_supported": [ "iss", "sub", "aud", "exp", "iat" ] }I did not spend much time configuring OpenID. Our config could go on a diet!
Sample response http://localhost:3000/oauth/discovery/keys
{ "keys": [ { "kty": "RSA", "kid": "-adZg-rJTQAJTWbh_R9Ar-VPdMR3Rz6tTt8gN9zMu3Y", "e": "AQAB", "n": "2cfIXkL6aYBETmJOHDwvtN-uls3ayCRILF0VfmEonkytaZnUcK4UP7QVuvqdbZiRUzOx0HroQYyoflHPhZtHzwgQl2wYC8qfPp3lmljydh9w9yO0kBMgQbuUl0YxemqrZCuTaW0mZtvYFp5daBflvBcnHwNVN5kRkMdR6VzP8vgfChjDzaNBMlPVvAfx5DFKjnvinxZoCuL2dEZS9pWcp6pGGO2ZTXPumBh9pQsooLwxcN0AYo0ZN1z3ZeKtQuH9hxhFWr-bNvEFWgx5d8nx1UFl6D3AySkin4LmJVBcqZ7VHiHxbc4jVH64-d8oWs3DgvYW8iq9I6EP988uviMUEw", "use": "sig", "alg": "RS256" } ] }