token_authority 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -1
- data/README.md +52 -14
- data/app/controllers/concerns/token_authority/initial_access_token_authentication.rb +2 -2
- data/app/controllers/token_authority/protected_resource_metadata_controller.rb +39 -0
- data/app/helpers/token_authority/authorization_grants_helper.rb +2 -3
- data/app/models/concerns/token_authority/claim_validatable.rb +2 -2
- data/app/models/concerns/token_authority/resourceable.rb +2 -2
- data/app/models/token_authority/access_token.rb +2 -2
- data/app/models/token_authority/access_token_request.rb +1 -1
- data/app/models/token_authority/authorization_request.rb +2 -2
- data/app/models/token_authority/authorization_server_metadata.rb +4 -4
- data/app/models/token_authority/client.rb +4 -4
- data/app/models/token_authority/client_metadata_document.rb +2 -2
- data/app/models/token_authority/client_registration_request.rb +5 -5
- data/app/models/token_authority/jwks_fetcher.rb +1 -1
- data/app/models/token_authority/protected_resource_metadata.rb +110 -31
- data/app/models/token_authority/refresh_token.rb +2 -2
- data/app/models/token_authority/refresh_token_request.rb +1 -1
- data/lib/generators/token_authority/install/templates/token_authority.rb +100 -114
- data/lib/token_authority/configuration.rb +345 -175
- data/lib/token_authority/errors.rb +29 -0
- data/lib/token_authority/routing/constraints.rb +2 -2
- data/lib/token_authority/routing/routes.rb +74 -16
- data/lib/token_authority/version.rb +1 -1
- data/lib/token_authority.rb +2 -2
- metadata +2 -2
- data/app/controllers/token_authority/resource_metadata_controller.rb +0 -12
|
@@ -218,4 +218,33 @@ module TokenAuthority
|
|
|
218
218
|
super
|
|
219
219
|
end
|
|
220
220
|
end
|
|
221
|
+
|
|
222
|
+
# Raised when no protected resource configuration exists for the requested subdomain.
|
|
223
|
+
#
|
|
224
|
+
# This error occurs in the RFC 9728 protected resource metadata endpoint when:
|
|
225
|
+
# 1. A subdomain-specific request arrives but that subdomain isn't in protected_resources
|
|
226
|
+
# 2. The fallback protected_resource configuration is also empty or nil
|
|
227
|
+
# 3. A bare domain request arrives but protected_resource isn't configured
|
|
228
|
+
#
|
|
229
|
+
# The ResourceMetadataController catches this error and returns HTTP 404, which is
|
|
230
|
+
# semantically correct: the client is asking about a resource that doesn't exist in
|
|
231
|
+
# the configuration. This differs from a 500 error which would imply a server problem.
|
|
232
|
+
#
|
|
233
|
+
# This separation of concerns (model raises domain error, controller maps to HTTP status)
|
|
234
|
+
# keeps the model focused on business logic without coupling it to HTTP semantics.
|
|
235
|
+
#
|
|
236
|
+
# @example Subdomain not configured
|
|
237
|
+
# # config.protected_resources = { "api" => {...} }
|
|
238
|
+
# # Request to mcp.example.com/.well-known/oauth-protected-resource
|
|
239
|
+
# # Raises this error because "mcp" isn't configured
|
|
240
|
+
#
|
|
241
|
+
# @see ResourceMetadataController#show
|
|
242
|
+
# @since 0.3.0
|
|
243
|
+
class ResourceNotConfiguredError < StandardError
|
|
244
|
+
# Creates a new ResourceNotConfiguredError.
|
|
245
|
+
# @param msg [String] custom error message
|
|
246
|
+
def initialize(msg = "No protected resource configuration found for this subdomain")
|
|
247
|
+
super
|
|
248
|
+
end
|
|
249
|
+
end
|
|
221
250
|
end
|
|
@@ -62,9 +62,9 @@ module TokenAuthority
|
|
|
62
62
|
# Determines if dynamic client registration is enabled in the configuration.
|
|
63
63
|
#
|
|
64
64
|
# @param _request [ActionDispatch::Request] the Rails request object (unused)
|
|
65
|
-
# @return [Boolean] true if
|
|
65
|
+
# @return [Boolean] true if dynamic client registration is enabled
|
|
66
66
|
def matches?(_request)
|
|
67
|
-
TokenAuthority.config.
|
|
67
|
+
TokenAuthority.config.dcr_enabled
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
end
|
|
@@ -4,36 +4,94 @@ module ActionDispatch
|
|
|
4
4
|
module Routing
|
|
5
5
|
class Mapper
|
|
6
6
|
##
|
|
7
|
-
#
|
|
8
|
-
# (RFC 8414, RFC 9728) and mounts the TokenAuthority engine.
|
|
7
|
+
# Registers authorization server routes including OAuth endpoints and RFC 8414 metadata.
|
|
9
8
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
9
|
+
# This is the primary route helper for setting up OAuth authorization server functionality.
|
|
10
|
+
# It registers two things:
|
|
11
|
+
# 1. The RFC 8414 metadata endpoint at /.well-known/oauth-authorization-server
|
|
12
|
+
# 2. The full TokenAuthority engine at your chosen mount path
|
|
12
13
|
#
|
|
13
|
-
#
|
|
14
|
+
# The metadata endpoint receives the mount path as a parameter so it can generate
|
|
15
|
+
# correct URLs for the authorization and token endpoints in its response. This allows
|
|
16
|
+
# clients to discover the OAuth endpoints dynamically.
|
|
14
17
|
#
|
|
15
|
-
# @
|
|
18
|
+
# @param at [String] mount path for OAuth endpoints (default: "/oauth")
|
|
19
|
+
#
|
|
20
|
+
# @example Basic usage
|
|
16
21
|
# Rails.application.routes.draw do
|
|
17
|
-
#
|
|
22
|
+
# token_authority_auth_server_routes
|
|
23
|
+
# # Creates routes at /oauth/authorize, /oauth/token, etc.
|
|
24
|
+
# # Metadata at /.well-known/oauth-authorization-server
|
|
18
25
|
# end
|
|
19
26
|
#
|
|
20
|
-
# @example
|
|
27
|
+
# @example Authorization server on dedicated subdomain
|
|
21
28
|
# Rails.application.routes.draw do
|
|
22
|
-
#
|
|
29
|
+
# constraints subdomain: "auth" do
|
|
30
|
+
# token_authority_auth_server_routes
|
|
31
|
+
# # Creates https://auth.example.com/oauth/authorize, etc.
|
|
32
|
+
# end
|
|
23
33
|
# end
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
#
|
|
35
|
+
# @example Custom mount path
|
|
36
|
+
# token_authority_auth_server_routes(at: "/oauth2")
|
|
37
|
+
# # Creates /oauth2/authorize, /oauth2/token instead of /oauth/*
|
|
38
|
+
#
|
|
39
|
+
def token_authority_auth_server_routes(at: "/oauth")
|
|
26
40
|
get "/.well-known/oauth-authorization-server",
|
|
27
41
|
to: "token_authority/metadata#show",
|
|
28
42
|
defaults: {mount_path: at}
|
|
29
43
|
|
|
30
|
-
# RFC 9728: Protected Resource Metadata
|
|
31
|
-
get "/.well-known/oauth-protected-resource",
|
|
32
|
-
to: "token_authority/resource_metadata#show",
|
|
33
|
-
defaults: {mount_path: at}
|
|
34
|
-
|
|
35
44
|
mount TokenAuthority::Engine => at
|
|
36
45
|
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# Registers RFC 9728 Protected Resource Metadata endpoint for client discovery.
|
|
49
|
+
#
|
|
50
|
+
# Creates a route at /.well-known/oauth-protected-resource that returns metadata
|
|
51
|
+
# about the protected resource, including which authorization servers can issue
|
|
52
|
+
# tokens for it, what scopes are supported, and how to present bearer tokens.
|
|
53
|
+
#
|
|
54
|
+
# This helper is designed to be called multiple times with different subdomain
|
|
55
|
+
# constraints, enabling a single Rails application to serve metadata for multiple
|
|
56
|
+
# protected resources. The controller extracts the subdomain from each request and
|
|
57
|
+
# looks it up as a symbol key in config.resources to find the appropriate metadata.
|
|
58
|
+
#
|
|
59
|
+
# For single-resource deployments, configure one entry in config.resources - it will
|
|
60
|
+
# be used as the fallback for any request. For multi-resource deployments, configure
|
|
61
|
+
# entries for each subdomain. The first entry in config.resources is used as the
|
|
62
|
+
# fallback when no subdomain matches.
|
|
63
|
+
#
|
|
64
|
+
# Returns 404 if config.resources is empty.
|
|
65
|
+
#
|
|
66
|
+
# @example Single protected resource
|
|
67
|
+
# Rails.application.routes.draw do
|
|
68
|
+
# token_authority_auth_server_routes
|
|
69
|
+
# token_authority_protected_resource_route
|
|
70
|
+
# # Serves metadata from first entry in config.resources
|
|
71
|
+
# end
|
|
72
|
+
#
|
|
73
|
+
# @example Multiple protected resources at different subdomains
|
|
74
|
+
# Rails.application.routes.draw do
|
|
75
|
+
# token_authority_auth_server_routes
|
|
76
|
+
#
|
|
77
|
+
# # REST API protected resource
|
|
78
|
+
# constraints subdomain: "api" do
|
|
79
|
+
# token_authority_protected_resource_route
|
|
80
|
+
# # Serves metadata from config.resources[:api]
|
|
81
|
+
# end
|
|
82
|
+
#
|
|
83
|
+
# # MCP server protected resource
|
|
84
|
+
# constraints subdomain: "mcp" do
|
|
85
|
+
# token_authority_protected_resource_route
|
|
86
|
+
# # Serves metadata from config.resources[:mcp]
|
|
87
|
+
# end
|
|
88
|
+
# end
|
|
89
|
+
#
|
|
90
|
+
# @see https://www.rfc-editor.org/rfc/rfc9728.html RFC 9728
|
|
91
|
+
def token_authority_protected_resource_route
|
|
92
|
+
get "/.well-known/oauth-protected-resource",
|
|
93
|
+
to: "token_authority/protected_resource_metadata#show"
|
|
94
|
+
end
|
|
37
95
|
end
|
|
38
96
|
end
|
|
39
97
|
end
|
data/lib/token_authority.rb
CHANGED
|
@@ -19,8 +19,8 @@ require "token_authority/routing/routes"
|
|
|
19
19
|
# @example Basic configuration
|
|
20
20
|
# TokenAuthority.configure do |config|
|
|
21
21
|
# config.secret_key = Rails.application.credentials.secret_key_base
|
|
22
|
-
# config.
|
|
23
|
-
# config.
|
|
22
|
+
# config.token_audience_url = "https://api.example.com"
|
|
23
|
+
# config.token_issuer_url = "https://example.com"
|
|
24
24
|
# end
|
|
25
25
|
#
|
|
26
26
|
# @since 0.2.0
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: token_authority
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dick Davis
|
|
@@ -56,7 +56,7 @@ files:
|
|
|
56
56
|
- app/controllers/token_authority/authorizations_controller.rb
|
|
57
57
|
- app/controllers/token_authority/clients_controller.rb
|
|
58
58
|
- app/controllers/token_authority/metadata_controller.rb
|
|
59
|
-
- app/controllers/token_authority/
|
|
59
|
+
- app/controllers/token_authority/protected_resource_metadata_controller.rb
|
|
60
60
|
- app/controllers/token_authority/sessions_controller.rb
|
|
61
61
|
- app/helpers/token_authority/authorization_grants_helper.rb
|
|
62
62
|
- app/models/concerns/token_authority/claim_validatable.rb
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module TokenAuthority
|
|
4
|
-
##
|
|
5
|
-
# Controller for RFC 9728 OAuth 2.0 Protected Resource Metadata
|
|
6
|
-
class ResourceMetadataController < ActionController::API
|
|
7
|
-
def show
|
|
8
|
-
metadata = ProtectedResourceMetadata.new(mount_path: params[:mount_path])
|
|
9
|
-
render json: metadata.to_h
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
end
|