Module: LcpRuby::Authentication::OidcBearerResolver

Defined in:
lib/lcp_ruby/authentication/oidc_bearer_resolver.rb

Overview

Glue between BearerJwtVerifier and UserResolver, registered with LcpRuby::ApiTokens::ResolverRegistry. The matcher (‘jwt_shape?`) is intentionally cheap — it does not verify the signature or look up keys — so non-JWT tokens (PATs, garbage) fall through to other resolvers.

Constant Summary collapse

RESOLVER_PRIORITY =

Priority 50 — PAT resolver at 100 always wins for ‘lcp_pat_*` tokens.

50

Class Method Summary collapse

Class Method Details

.jwt_shape?(token) ⇒ Boolean

Cheap shape check. Three dot-separated base64url segments where the first segment decodes to a JSON object containing an ‘alg`. Returns false fast on PATs, opaque tokens, garbage.

Returns:

  • (Boolean)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/lcp_ruby/authentication/oidc_bearer_resolver.rb', line 33

def jwt_shape?(token)
  return false if token.nil? || token.to_s.empty?

  parts = token.split(".")
  return false unless parts.size == 3
  parts.each { |p| return false if p.empty? }

  header_json = decode_b64url(parts.first)
  return false unless header_json

  header = JSON.parse(header_json)
  header.is_a?(Hash) && !header["alg"].to_s.empty?
rescue JSON::ParserError
  false
end

.register!Object

Registers this module with the API-token ResolverRegistry. Called from the engine initializer at boot and from TestSupport at test time, so both paths agree on priority/matcher/resolver.



21
22
23
24
25
26
27
28
# File 'lib/lcp_ruby/authentication/oidc_bearer_resolver.rb', line 21

def register!
  LcpRuby::ApiTokens::ResolverRegistry.register(
    :oidc_bearer,
    priority: RESOLVER_PRIORITY,
    matcher:  ->(t) { jwt_shape?(t) },
    resolver: ->(t) { resolve(t) }
  )
end

.resolve(token) ⇒ Object

Returns the resolved User on success, nil otherwise. Swallows the validator/resolver exceptions that mean “bad token → 401” and the ConfigurationError raised by ‘RoleMapper#resolve_db` when role_source: db is misconfigured (otherwise every API request would 500 instead of 401). Other exceptions propagate.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/lcp_ruby/authentication/oidc_bearer_resolver.rb', line 54

def resolve(token)
  claims, provider = BearerJwtVerifier.verify(token)
  return nil unless claims

  UserResolver.from_claims(claims: claims, provider: provider)
rescue HostRejected, NoRoleMatch, InvalidClaims => e
  Rails.logger.info(
    "[lcp_ruby] OIDC bearer rejected: #{e.class}: #{e.message}"
  ) if defined?(Rails)
  nil
rescue ConfigurationError => e
  Rails.logger.warn(
    "[lcp_ruby] OIDC bearer rejected — operator misconfiguration: #{e.message}"
  ) if defined?(Rails)
  nil
end