Add Spring Authorization Server project: OAuth2/OIDC provider, client and resource server
Three modules on Spring Boot 4.1.1 with Spring Authorization Server 7.1.1: the provider
itself, a relying party, and an API that trusts its tokens. Client registration, PKCE,
a custom consent page and token customisation, with profiles that make each failure
reproducible.
Every claim is backed by captured output in docs/output/as-*.txt, regenerated by
authorization-server/scripts/run-all.sh. Notable findings, verified against the jars:
- OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity) was deleted
in 7.0, and both configuration classes moved into spring-security-config
- ClientSettings.requireProofKey flipped from false to true, on the authorization server
(1.5.8 -> 7.1.1) and on the OAuth2 client (6.5.1 -> 7.1.1)
- requireProofKey(false) does not make PKCE optional for a public client; the code
verifier is that client's only authentication at the token endpoint
- MediaTypeRequestMatcher(TEXT_HTML) matches Accept: */*, so the token endpoint answers
API callers with 302 -> /login unless setIgnoredMediaTypes(ALL) is called
Also renames the repository to spring-auth-demo and cross-links the new chapter set from
the existing documentation.
This commit is contained in:
240
docs/output/as-discovery.txt
Normal file
240
docs/output/as-discovery.txt
Normal file
@@ -0,0 +1,240 @@
|
||||
|
||||
------------------------------------------------------------------
|
||||
== OpenID Connect discovery: GET /.well-known/openid-configuration
|
||||
------------------------------------------------------------------
|
||||
$ curl -s http://localhost:9000/.well-known/openid-configuration
|
||||
{
|
||||
"issuer": "http://localhost:9000",
|
||||
"authorization_endpoint": "http://localhost:9000/oauth2/authorize",
|
||||
"token_endpoint": "http://localhost:9000/oauth2/token",
|
||||
"token_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
"client_secret_jwt",
|
||||
"private_key_jwt",
|
||||
"tls_client_auth",
|
||||
"self_signed_tls_client_auth"
|
||||
],
|
||||
"jwks_uri": "http://localhost:9000/oauth2/jwks",
|
||||
"userinfo_endpoint": "http://localhost:9000/userinfo",
|
||||
"end_session_endpoint": "http://localhost:9000/connect/logout",
|
||||
"response_types_supported": [
|
||||
"code"
|
||||
],
|
||||
"grant_types_supported": [
|
||||
"authorization_code",
|
||||
"client_credentials",
|
||||
"refresh_token",
|
||||
"urn:ietf:params:oauth:grant-type:token-exchange"
|
||||
],
|
||||
"revocation_endpoint": "http://localhost:9000/oauth2/revoke",
|
||||
"revocation_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
"client_secret_jwt",
|
||||
"private_key_jwt",
|
||||
"tls_client_auth",
|
||||
"self_signed_tls_client_auth"
|
||||
],
|
||||
"introspection_endpoint": "http://localhost:9000/oauth2/introspect",
|
||||
"introspection_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
"client_secret_jwt",
|
||||
"private_key_jwt",
|
||||
"tls_client_auth",
|
||||
"self_signed_tls_client_auth"
|
||||
],
|
||||
"code_challenge_methods_supported": [
|
||||
"S256"
|
||||
],
|
||||
"tls_client_certificate_bound_access_tokens": true,
|
||||
"dpop_signing_alg_values_supported": [
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"PS256",
|
||||
"PS384",
|
||||
"PS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512"
|
||||
],
|
||||
"subject_types_supported": [
|
||||
"public"
|
||||
],
|
||||
"id_token_signing_alg_values_supported": [
|
||||
"RS256"
|
||||
],
|
||||
"scopes_supported": [
|
||||
"openid"
|
||||
]
|
||||
}
|
||||
|
||||
------------------------------------------------------------------
|
||||
== OAuth2 metadata: GET /.well-known/oauth-authorization-server
|
||||
------------------------------------------------------------------
|
||||
Present even with .oidc(...) switched off. The OIDC document above is the one
|
||||
that additionally advertises userinfo_endpoint and id_token signing algorithms.
|
||||
$ curl -s http://localhost:9000/.well-known/oauth-authorization-server
|
||||
{
|
||||
"issuer": "http://localhost:9000",
|
||||
"authorization_endpoint": "http://localhost:9000/oauth2/authorize",
|
||||
"token_endpoint": "http://localhost:9000/oauth2/token",
|
||||
"token_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
"client_secret_jwt",
|
||||
"private_key_jwt",
|
||||
"tls_client_auth",
|
||||
"self_signed_tls_client_auth"
|
||||
],
|
||||
"jwks_uri": "http://localhost:9000/oauth2/jwks",
|
||||
"response_types_supported": [
|
||||
"code"
|
||||
],
|
||||
"grant_types_supported": [
|
||||
"authorization_code",
|
||||
"client_credentials",
|
||||
"refresh_token",
|
||||
"urn:ietf:params:oauth:grant-type:token-exchange"
|
||||
],
|
||||
"revocation_endpoint": "http://localhost:9000/oauth2/revoke",
|
||||
"revocation_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
"client_secret_jwt",
|
||||
"private_key_jwt",
|
||||
"tls_client_auth",
|
||||
"self_signed_tls_client_auth"
|
||||
],
|
||||
"introspection_endpoint": "http://localhost:9000/oauth2/introspect",
|
||||
"introspection_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
"client_secret_post",
|
||||
"client_secret_jwt",
|
||||
"private_key_jwt",
|
||||
"tls_client_auth",
|
||||
"self_signed_tls_client_auth"
|
||||
],
|
||||
"code_challenge_methods_supported": [
|
||||
"S256"
|
||||
],
|
||||
"tls_client_certificate_bound_access_tokens": true,
|
||||
"dpop_signing_alg_values_supported": [
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"PS256",
|
||||
"PS384",
|
||||
"PS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512"
|
||||
]
|
||||
}
|
||||
|
||||
------------------------------------------------------------------
|
||||
== JWK Set: GET /oauth2/jwks
|
||||
------------------------------------------------------------------
|
||||
Public keys only. No 'd' member - if you ever see one here, stop the server.
|
||||
{
|
||||
"keys": [
|
||||
{
|
||||
"kty": "RSA",
|
||||
"e": "AQAB",
|
||||
"kid": "262bd550-3657-46c4-bafc-cce4c6f4e0cb",
|
||||
"n": "pFCIstpVnGQm7Mp8bskE_-_Rz-oI6mPaiyQLiWMBuVip4fkKYwapZVbsZf9fmy1w1KXWIdtXOhe-fqa3-KqYzsrje-o2u6_D27rqR1Z0I9ezbDfw2A4Gsj5AlmnXzWMLnNMzSueSf8luRk04MHO4bGzXLqQ1gOltnqMkMAQzhCqWFZmKxNJeaB4FlXOtxqzcso0eeKsPzRjZvTamgU5TvGUZmQ4LTKTkoYzB3kjvCspVpZAbdVR01RlmzfTJB0tVIc0ioMk1YZHUx27TPN1W8Nw1AaAYmV9URaf2fgz2Ja3y_Lj8hmXuQAcPOGBmoVWX0QkW4DTSAPW0xiPHqpjw9Q"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
------------------------------------------------------------------
|
||||
== Resolved endpoint settings, read back from AuthorizationServerSettings
|
||||
------------------------------------------------------------------
|
||||
{
|
||||
"settings.authorization-server.client-registration-endpoint": "/oauth2/register",
|
||||
"settings.authorization-server.authorization-endpoint": "/oauth2/authorize",
|
||||
"settings.authorization-server.token-endpoint": "/oauth2/token",
|
||||
"settings.authorization-server.device-verification-endpoint": "/oauth2/device_verification",
|
||||
"settings.authorization-server.oidc-user-info-endpoint": "/userinfo",
|
||||
"settings.authorization-server.pushed-authorization-request-endpoint": "/oauth2/par",
|
||||
"settings.authorization-server.oidc-client-registration-endpoint": "/connect/register",
|
||||
"settings.authorization-server.oidc-logout-endpoint": "/connect/logout",
|
||||
"settings.authorization-server.issuer": "http://localhost:9000",
|
||||
"settings.authorization-server.multiple-issuers-allowed": false,
|
||||
"settings.authorization-server.device-authorization-endpoint": "/oauth2/device_authorization",
|
||||
"settings.authorization-server.jwk-set-endpoint": "/oauth2/jwks",
|
||||
"settings.authorization-server.token-revocation-endpoint": "/oauth2/revoke",
|
||||
"settings.authorization-server.token-introspection-endpoint": "/oauth2/introspect"
|
||||
}
|
||||
|
||||
------------------------------------------------------------------
|
||||
== Registered clients, as the server actually holds them
|
||||
------------------------------------------------------------------
|
||||
[
|
||||
{
|
||||
"clientId": "demo-web",
|
||||
"authenticationMethods": [
|
||||
"client_secret_basic"
|
||||
],
|
||||
"grantTypes": [
|
||||
"refresh_token",
|
||||
"authorization_code"
|
||||
],
|
||||
"redirectUris": [
|
||||
"http://127.0.0.1:8080/login/oauth2/code/demo-web"
|
||||
],
|
||||
"scopes": [
|
||||
"orders.write",
|
||||
"openid",
|
||||
"profile",
|
||||
"orders.read"
|
||||
],
|
||||
"requireProofKey": true,
|
||||
"requireAuthorizationConsent": true,
|
||||
"accessTokenFormat": "self-contained",
|
||||
"accessTokenTtlSeconds": 300,
|
||||
"reuseRefreshTokens": false
|
||||
},
|
||||
{
|
||||
"clientId": "demo-spa",
|
||||
"authenticationMethods": [
|
||||
"none"
|
||||
],
|
||||
"grantTypes": [
|
||||
"refresh_token",
|
||||
"authorization_code"
|
||||
],
|
||||
"redirectUris": [
|
||||
"http://127.0.0.1:8080/authorized"
|
||||
],
|
||||
"scopes": [
|
||||
"openid",
|
||||
"orders.read"
|
||||
],
|
||||
"requireProofKey": true,
|
||||
"requireAuthorizationConsent": true,
|
||||
"accessTokenFormat": "self-contained",
|
||||
"accessTokenTtlSeconds": 300,
|
||||
"reuseRefreshTokens": true
|
||||
},
|
||||
{
|
||||
"clientId": "demo-service",
|
||||
"authenticationMethods": [
|
||||
"client_secret_basic"
|
||||
],
|
||||
"grantTypes": [
|
||||
"client_credentials"
|
||||
],
|
||||
"redirectUris": [],
|
||||
"scopes": [
|
||||
"orders.read"
|
||||
],
|
||||
"requireProofKey": true,
|
||||
"requireAuthorizationConsent": false,
|
||||
"accessTokenFormat": "self-contained",
|
||||
"accessTokenTtlSeconds": 600,
|
||||
"reuseRefreshTokens": true
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user