summaryrefslogtreecommitdiff
path: root/bin/idp
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-03-17 20:36:48 -0600
committermo khan <mo@mokhan.ca>2025-03-17 20:36:48 -0600
commit0e5426ad0026d52a44dd7c0e76a894860022bb34 (patch)
tree7a9f4d82424af48cfa669181c3737b408836f202 /bin/idp
parent2cf2473bc4cab2ffd1b826c16a3b5ea5dc0f950a (diff)
feat: exchange an authorization grant for a token
Diffstat (limited to 'bin/idp')
-rwxr-xr-xbin/idp61
1 files changed, 55 insertions, 6 deletions
diff --git a/bin/idp b/bin/idp
index 622faa19..23510bd2 100755
--- a/bin/idp
+++ b/bin/idp
@@ -378,6 +378,50 @@ module Authz
end
end
+ class AuthorizationGrant
+ class << self
+ def all
+ @all ||= []
+ end
+
+ # 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
+ end
+ end
+
+ def create!(user)
+ new(user).tap do |grant|
+ all << grant
+ end
+ end
+ end
+
+ attr_reader :code, :user
+
+ def initialize(user)
+ @user = user
+ @code = SecureRandom.uuid
+ @exchanged_at = nil
+ end
+
+ def used?
+ @exchanged_at
+ end
+
+ def create_access_token
+ raise "Invalid code" if used?
+
+ @exchanged_at = Time.now
+ user.create_access_token
+ end
+ end
+
class OAuthController
include ::HTTPHelpers
@@ -407,10 +451,13 @@ module Authz
when "/oauth/authorize" # RFC-6749
return post_authorize(request)
when "/oauth/token" # RFC-6749
- # TODO:: Look up authorization grant by (code, saml_assertion)
- user = Authn::User.new(id: SecureRandom.uuid)
- return [200, { 'Content-Type' => "application/json" }, [JSON.pretty_generate({
- access_token: user.create_access_token.to_jwt,
+ 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,
@@ -453,13 +500,15 @@ module Authz
def post_authorize(request)
params = request.params.slice('client_id', 'redirect_uri', 'response_type', 'response_mode', 'state', 'code_challenge_method', 'code_challenge', 'scope')
+
+ grant = AuthorizationGrant.create!(current_user(request))
case params['response_type']
when 'code'
case params['response_mode']
when 'fragment'
- return [302, { 'Location' => "#{params['redirect_uri']}#code=#{SecureRandom.uuid}&state=#{params['state']}" }, []]
+ return [302, { 'Location' => "#{params['redirect_uri']}#code=#{grant.code}&state=#{params['state']}" }, []]
when 'query'
- return [302, { 'Location' => "#{params['redirect_uri']}?code=#{SecureRandom.uuid}&state=#{params['state']}" }, []]
+ return [302, { 'Location' => "#{params['redirect_uri']}?code=#{grant.code}&state=#{params['state']}" }, []]
else
# TODO:: form post
end