From 66edae4510b51570e6e4a21ef38dfc7defb63982 Mon Sep 17 00:00:00 2001 From: mo khan Date: Mon, 17 Mar 2025 20:53:09 -0600 Subject: refactor: add shim to handle other types of authorization grants --- bin/idp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 23 deletions(-) (limited to 'bin/idp') diff --git a/bin/idp b/bin/idp index 23510bd..d612e79 100755 --- a/bin/idp +++ b/bin/idp @@ -79,9 +79,9 @@ module Authn end end - def find_by_credentials(params = {}) - user = find_by_username(params["username"]) - user&.valid_password?(params["password"]) ? user : nil + def login(params = {}) + user = find_by_username(params[:username]) + user&.valid_password?(params[:password]) ? user : nil end end @@ -148,7 +148,7 @@ module Authn when Rack::POST case request.path when '/sessions' - if (user = User.find_by_credentials(request.params)) + if (user = User.login(request.params.transform_keys(&:to_sym))) request.session[:user_id] = user[:id] path = request.params["redirect_back"] ? request.params["redirect_back"] : "/" return http_redirect_to(path) @@ -387,14 +387,48 @@ module Authz # TODO:: Look up saml_assertion def find_by(params) case params[:grant_type] - when "authorization_code" - # TODO:: implement `code_verifier` param - all.find do |grant| - grant.code == params[:code] - end + when 'authorization_code' + authorization_code_grant(params[:code], params[:code_verifier]) + when 'refresh_token' + refresh_grant(params[:refresh_token]) + when 'client_credentials' + client_credentials_grant(params) + when 'password' + password_grant(params[:username], params[:password]) + when 'urn:ietf:params:oauth:grant-type:saml2-bearer' # RFC7522 + saml_assertion_grant(params[:assertion]) + when 'urn:ietf:params:oauth:grant-type:jwt-bearer' # RFC7523 + jwt_bearer_grant(params) + end + end + + # TODO:: implement `code_verifier` param + def authorization_code_grant(code, code_verifier) + all.find do |grant| + grant.active? && grant.code == code end end + def refresh_grant(refresh_token) + raise NotImplementedError + end + + def client_credential_grant(params) + raise NotImplementedError + end + + def password_grant(username, password) + raise NotImplementedError + end + + def saml_assertion_grant(saml_assertion) + raise NotImplementedError + end + + def jwt_bearer_grant(params) + raise NotImplementedError + end + def create!(user) new(user).tap do |grant| all << grant @@ -410,15 +444,30 @@ module Authz @exchanged_at = nil end - def used? - @exchanged_at + def active? + @exchanged_at.nil? + end + + def inactive? + !active? end def create_access_token - raise "Invalid code" if used? + raise "Invalid code" unless active? - @exchanged_at = Time.now - user.create_access_token + user.create_access_token.tap do + @exchanged_at = Time.now + end + end + + def exchange + { + access_token: create_access_token.to_jwt, + token_type: "Bearer", + issued_token_type: "urn:ietf:params:oauth:token-type:access_token", + expires_in: 3600, + refresh_token: SecureRandom.hex(32) + } end end @@ -452,17 +501,10 @@ module Authz return post_authorize(request) when "/oauth/token" # RFC-6749 params = request.content_type == "application/json" ? JSON.parse(request.body.read, symbolize_names: true) : Hash[URI.decode_www_form(request.body.read)].transform_keys(&:to_sym) - puts params.inspect grant = AuthorizationGrant.find_by(params) - return [404, { "Content-Type" => "application/json" }, [JSON.pretty_generate({ error: 404, message: "Not Found" })]] if grant.nil? || grant.used? - return [200, { "Content-Type" => "application/json" }, [JSON.pretty_generate({ - access_token: grant.create_access_token.to_jwt, - token_type: "Bearer", - issued_token_type: "urn:ietf:params:oauth:token-type:access_token", - expires_in: 3600, - refresh_token: SecureRandom.hex(32) - })]] + return [404, { "Content-Type" => "application/json" }, [JSON.pretty_generate(error: 404, message: "Not Found")]] if grant.nil? || grant.inactive? + return [200, { "Content-Type" => "application/json" }, [JSON.pretty_generate(grant.exchange)]] when "/oauth/revoke" # RFC-7009 # TODO:: Revoke the JWT token and make it ineligible for usage return http_not_found -- cgit v1.2.3