diff options
| author | mo khan <mo@mokhan.ca> | 2025-02-28 15:23:06 -0700 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-02-28 15:23:06 -0700 |
| commit | 68f60576334bb0db8c8d9c579b3d60326aaff512 (patch) | |
| tree | d2c8b7e1c085d627b6e1358c4eb32a757c1fb299 /bin/idp | |
| parent | f6f82b707e85eec65e8dbc4066192751fc1f2522 (diff) | |
feat: implement more of the OIDC workflow
Diffstat (limited to 'bin/idp')
| -rwxr-xr-x | bin/idp | 130 |
1 files changed, 86 insertions, 44 deletions
@@ -50,10 +50,49 @@ class IdentityProvider @storage = {} end + def call(env) + path = env['PATH_INFO'] + case env['REQUEST_METHOD'] + when 'GET' + case path + when '/.well-known/openid-configuration' + return openid_metadata + when '/.well-known/oauth-authorization-server' + return oauth_metadata + when '/.well-known/webfinger' # RFC-7033 + return not_found + when "/metadata.xml" + return saml_metadata + when "/sessions/new" + return saml_post_back(Rack::Request.new(env)) + when "/oauth/authorize" # RFC-6749 + return get_authorize(Rack::Request.new(env)) + else + return not_found + end + when 'POST' + case path + when "/sessions/new" + return saml_post_back(Rack::Request.new(env)) + when "/oauth/authorize" # RFC-6749 + return post_authorize(Rack::Request.new(env)) + when "/oauth/token" # RFC-6749 + return not_found + when "/oauth/revoke" # RFC-7009 + return not_found + else + return not_found + end + end + not_found + end + + private + # Download IDP Metadata # # GET /metadata.xml - def metadata + def saml_metadata xml = Saml::Kit::Metadata.build_xml do |builder| builder.contact_email = 'hi@example.com' builder.organization_name = "Acme, Inc" @@ -96,17 +135,58 @@ class IdentityProvider })]] end + def get_authorize(request) + template = <<~ERB + <!doctype html> + <html> + <head><title></title></head> + <body> + <h2>Authorize?</h2> + <form action="/oauth/authorize" method="post"> + <input type="hidden" name="client_id" value="<%= request.params['client_id'] %>" /> + <input type="hidden" name="scope" value="<%= request.params['scope'] %>" /> + <input type="hidden" name="redirect_uri" value="<%= request.params['redirect_uri'] %>" /> + <input type="hidden" name="response_mode" value="<%= request.params['response_mode'] %>" /> + <input type="hidden" name="response_type" value="<%= request.params['response_type'] %>" /> + <input type="hidden" name="state" value="<%= request.params['state'] %>" /> + <input type="hidden" name="code_challenge_method" value="<%= request.params['code_challenge_method'] %>" /> + <input type="hidden" name="code_challenge" value="<%= request.params['code_challenge'] %>" /> + <input type="submit" value="Submit" /> + </form> + </body> + </html> + ERB + html = ERB.new(template, trim_mode: '-').result(binding) + [200, { 'Content-Type' => "text/html" }, [html]] + end + + def post_authorize(request) + params = request.params.slice('client_id', 'redirect_uri', 'response_type', 'response_mode', 'state', 'code_challenge_method', 'code_challenge', 'scope') + case params['response_type'] + when 'code' + case params['response_mode'] + when 'fragment' + return [302, { 'Location' => "#{params['redirect_uri']}#code=#{SecureRandom.uuid}&state=#{params['state']}" }, []] + when 'query' + return [302, { 'Location' => "#{params['redirect_uri']}?code=#{SecureRandom.uuid}&state=#{params['state']}" }, []] + else + # TODO:: form post + end + + when 'token' + return not_found + else + return not_found + end + end + # GET /.well-known/openid-configuration def openid_metadata [200, { 'Content-Type' => "application/json" }, [JSON.pretty_generate({ issuer: "http://localhost:8282/.well-known/oauth-authorization-server", authorization_endpoint: "http://localhost:8282/oauth/authorize", token_endpoint: "http://localhost:8282/oauth/token", - # token_endpoint_auth_methods_supported: [], - # token_endpoint_auth_signing_alg_values_supported: [], userinfo_endpoint: "http://localhost:8282/oidc/user/", - # check_session_iframe: nil, - # end_session_endpoint: nil, jwks_uri: "", # RFC-7517 registration_endpoint: nil, scopes_supported: ["openid", "profile", "email"], @@ -156,45 +236,7 @@ class IdentityProvider })]] end - # auth service - def call(env) - path = env['PATH_INFO'] - case env['REQUEST_METHOD'] - when 'GET' - case path - when '/.well-known/openid-configuration' - return openid_metadata - when '/.well-known/oauth-authorization-server' - return oauth_metadata - when '/.well-known/webfinger' # RFC-7033 - return not_found - when "/metadata.xml" - return metadata - when "/sessions/new" - return post_back(Rack::Request.new(env)) - when "oauth/authorize" # RFC-6749 - return not_found - else - return not_found - end - when 'POST' - case path - when "/sessions/new" - return post_back(Rack::Request.new(env)) - when "oauth/token" # RFC-6749 - return not_found - when "oauth/revoke" # RFC-7009 - return not_found - else - return not_found - end - end - not_found - end - - private - - def post_back(request) + def saml_post_back(request) params = saml_params_from(request) saml_request = binding_for(request).deserialize(params) @builder = nil |
