OpenID conformance test: we get a warning for not having a value for every claim. But we can explictly list support claims. Nothing we can do about a warning in the complience.

This commit is contained in:
Dan Milne
2026-01-02 16:35:12 +11:00
parent 182682024d
commit 9589d8cce3
3 changed files with 21 additions and 46 deletions

View File

@@ -30,7 +30,17 @@ class OidcController < ApplicationController
id_token_signing_alg_values_supported: ["RS256"],
scopes_supported: ["openid", "profile", "email", "groups", "offline_access"],
token_endpoint_auth_methods_supported: ["client_secret_post", "client_secret_basic"],
claims_supported: ["sub", "email", "email_verified", "name", "preferred_username", "groups", "admin", "auth_time", "acr", "azp", "at_hash"],
claims_supported: [
"sub", # Always included
"email", # email scope
"email_verified", # email scope
"name", # profile scope
"preferred_username", # profile scope
"updated_at", # profile scope
"groups" # groups scope
# Note: Custom claims are also supported but not listed here
# ID-token-only claims (auth_time, acr, azp, at_hash, nonce) are not listed
],
code_challenge_methods_supported: ["plain", "S256"],
backchannel_logout_supported: true,
backchannel_logout_session_supported: true
@@ -657,26 +667,13 @@ class OidcController < ApplicationController
end
# Profile claims (only if 'profile' scope requested)
# Per OIDC Core spec section 5.4, all profile claims SHOULD be returned
# Per OIDC Core spec section 5.4, include available profile claims
# Only include claims we have data for - omit unknown claims rather than returning null
if requested_scopes.include?("profile")
# Use username if available, otherwise email as preferred_username
claims[:preferred_username] = user.username.presence || user.email_address
# Name: use stored name or fall back to email
claims[:name] = user.name.presence || user.email_address
# Standard profile claims we don't store - set to nil (optional per spec)
claims[:given_name] = nil
claims[:family_name] = nil
claims[:middle_name] = nil
claims[:nickname] = nil
claims[:profile] = nil
claims[:picture] = nil
claims[:website] = nil
claims[:gender] = nil
claims[:birthdate] = nil
claims[:zoneinfo] = nil
claims[:locale] = nil
# Time the user's information was last updated
claims[:updated_at] = user.updated_at.to_i
end

View File

@@ -23,17 +23,10 @@ class OidcJwtService
iat: now
}
# Email claims (only if 'email' scope requested)
if requested_scopes.include?("email")
payload[:email] = user.email_address
payload[:email_verified] = true
end
# Profile claims (only if 'profile' scope requested)
if requested_scopes.include?("profile")
payload[:preferred_username] = user.username.presence || user.email_address
payload[:name] = user.name.presence || user.email_address
end
# NOTE: Email and profile claims are NOT included in the ID token for authorization code flow
# Per OIDC Core spec §5.4, these claims should only be returned via the UserInfo endpoint
# For implicit flow (response_type=id_token), claims would be included here, but we only
# support authorization code flow, so these claims are omitted from the ID token.
# Add nonce if provided (OIDC requires this for implicit flow)
payload[:nonce] = nonce if nonce.present?

View File

@@ -115,25 +115,10 @@ class OidcUserinfoControllerTest < ActionDispatch::IntegrationTest
# Required claims
assert json["sub"].present?
# All standard profile claims should be present (per OIDC Core spec section 5.4)
# Some may be null if we don't have the data, but the keys should exist
assert json.key?("name"), "Should include name claim"
assert json.key?("given_name"), "Should include given_name claim (may be null)"
assert json.key?("family_name"), "Should include family_name claim (may be null)"
assert json.key?("middle_name"), "Should include middle_name claim (may be null)"
assert json.key?("nickname"), "Should include nickname claim (may be null)"
assert json.key?("preferred_username"), "Should include preferred_username claim"
assert json.key?("profile"), "Should include profile claim (may be null)"
assert json.key?("picture"), "Should include picture claim (may be null)"
assert json.key?("website"), "Should include website claim (may be null)"
assert json.key?("gender"), "Should include gender claim (may be null)"
assert json.key?("birthdate"), "Should include birthdate claim (may be null)"
assert json.key?("zoneinfo"), "Should include zoneinfo claim (may be null)"
assert json.key?("locale"), "Should include locale claim (may be null)"
assert json.key?("updated_at"), "Should include updated_at claim"
# Verify preferred_username is using username or email
assert json["preferred_username"].present?, "preferred_username should have a value"
# Profile claims we support should be present
assert json["name"].present?, "Should include name with profile scope"
assert json["preferred_username"].present?, "Should include preferred_username with profile scope"
assert json["updated_at"].present?, "Should include updated_at with profile scope"
# Email claims should NOT be present
assert_nil json["email"], "Should not include email without email scope"