Module: Keycardai::OAuth::Discovery

Defined in:
lib/keycardai/oauth/discovery.rb

Overview

Internals of authorization-server discovery, shared with JWKSKeyring.

Class Method Summary collapse

Class Method Details

.metadata_url(issuer) ⇒ Object

RFC 8414: the well-known path segment is inserted between the host and any issuer path component.



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/keycardai/oauth/discovery.rb', line 54

def (issuer)
  raise ConfigurationError, "issuer must be a non-empty URL" if issuer.nil? || issuer.empty?

  uri = URI(issuer)
  raise ConfigurationError, "issuer must be an absolute http(s) URL" unless uri.is_a?(URI::HTTP)

  path = uri.path.chomp("/")
  uri.path = "/.well-known/oauth-authorization-server#{path}"
  uri.to_s
rescue URI::InvalidURIError
  raise ConfigurationError, "issuer is not a valid URL"
end

.parse_document(issuer, body) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/keycardai/oauth/discovery.rb', line 84

def parse_document(issuer, body)
  document = JSON.parse(body)
  unless document.is_a?(Hash)
    raise ProtocolError.new("metadata for #{issuer} is not a JSON object",
                            code: "invalid_metadata")
  end

  document
rescue JSON::ParserError
  raise ProtocolError.new("metadata for #{issuer} is not valid JSON", code: "invalid_metadata")
end

.parse_metadata(issuer, body) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/keycardai/oauth/discovery.rb', line 67

def (issuer, body)
  document = parse_document(issuer, body)
  validate_issuer(issuer, document)

  AuthorizationServerMetadata.new(
    issuer: document["issuer"],
    token_endpoint: document["token_endpoint"],
    authorization_endpoint: document["authorization_endpoint"],
    jwks_uri: document["jwks_uri"],
    registration_endpoint: document["registration_endpoint"],
    grant_types_supported: document["grant_types_supported"],
    token_endpoint_auth_methods_supported: document["token_endpoint_auth_methods_supported"],
    response_types_supported: document["response_types_supported"],
    raw: document
  )
end

.validate_issuer(issuer, document) ⇒ Object

RFC 8414 §3.3: the response issuer must be present and match the requested issuer, ignoring a trailing slash.

Raises:



98
99
100
101
102
103
104
105
106
# File 'lib/keycardai/oauth/discovery.rb', line 98

def validate_issuer(issuer, document)
  unless document["issuer"].is_a?(String)
    raise ProtocolError.new("metadata for #{issuer} has no issuer", code: "invalid_metadata")
  end
  return if document["issuer"].chomp("/") == issuer.chomp("/")

  raise ProtocolError.new("metadata issuer #{document["issuer"]} does not match requested issuer #{issuer}",
                          code: "issuer_mismatch")
end