Commit 159b5ab

mo khan <mo@mokhan.ca>
2025-02-28 22:38:33
feat: add a simple grant exchange endpoint
1 parent 68f6057
Changed files (2)
bin/idp
@@ -77,7 +77,12 @@ class IdentityProvider
       when "/oauth/authorize" # RFC-6749
         return post_authorize(Rack::Request.new(env))
       when "/oauth/token" # RFC-6749
-        return not_found
+        return [200, { 'Content-Type' => "application/json" }, [JSON.pretty_generate({
+          access_token: to_jwt(sub: SecureRandom.uuid, iat: Time.now.to_i),
+          token_type: "Bearer",
+          expires_in: 3600,
+          refresh_token: SecureRandom.hex(32)
+        })]]
       when "/oauth/revoke" # RFC-7009
         return not_found
       else
@@ -89,6 +94,14 @@ class IdentityProvider
 
   private
 
+  def to_jwt(claims)
+    [
+      Base64.strict_encode64(JSON.generate({alg: "RS256", typ: "JWT"})),
+      Base64.strict_encode64(JSON.generate(claims)),
+      Base64.strict_encode64(JSON.generate({})),
+    ].join(".")
+  end
+
   # Download IDP Metadata
   #
   # GET /metadata.xml
bin/sp
@@ -7,6 +7,7 @@ gemfile do
 
   gem "base64", "~> 0.1"
   gem "erb", "~> 4.0"
+  gem "net-hippie", "~> 1.0"
   gem "rack", "~> 3.0"
   gem "rackup", "~> 2.0"
   gem "saml-kit", "~> 1.0"
@@ -89,7 +90,16 @@ class ServiceProvider
 
   def oauth_callback(request)
     # TODO:: Exchange grant (authorization_code) for an access token
-    [200, { "Content-Type" => "application/json" }, [JSON.pretty_generate(request.params)]]
+    response = Net::Hippie.default_client.post(
+      "http://localhost:8282/oauth/token",
+      headers: { 'Authorization' => Net::Hippie.basic_auth('client_id', 'secret') },
+      body: {
+        grant_type: "authorization_code",
+        code: request.params['code'],
+        code_verifier: "not_implemented"
+      }
+    )
+    [200, { "Content-Type" => "application/json" }, [JSON.pretty_generate(request.params.merge(JSON.parse(response.body)))]]
   end
 
   def saml_post_to_idp(request)