You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the Issue
When I try to use the BFF pattern with an OIDC authentication server, in my case Keycloak, I encounter a bug:
In the link above at line 8, the issuer is assigned this value: ${reverse-proxy-uri}${authorization-server-prefix}/realms/baeldung
However, per the ClientRegistration class defined in org.springframework.security.oauth2.client.registration, at line 132, there's a comparison between, the issuer provider above and the actual issuer info that comes from the server.
If the server doesn't use the BFF pattern, this wouldn't be an issue, because this comparison will always be true.
However if the authentication server is between a Reverse-Proxy, aka gateway, then this comparison will be false because the BFF pattern modifies the issuer uri as per 1. and although that modified link still point to the right server, the code at line 132 above would make it fails because there's not a one-to-one match between the modified uri in the bff configuration and the one returned from the server
5. Server configuration link: http://localhost:8080/realms/myrealm/.well-known/openid-configuration
`{"issuer":"http://localhost:8080/realms/myrealm","authorization_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/auth","token_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/token","introspection_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/token/introspect","userinfo_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/userinfo","end_session_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/logout","frontchannel_logout_session_supported":true,"frontchannel_logout_supported":true,"jwks_uri":"http://localhost:8080/realms/myrealm/protocol/openid-connect/certs","check_session_iframe":"http://localhost:8080/realms/myrealm/protocol/openid-connect/login-status-iframe.html","grant_types_supported":["authorization_code","implicit","refresh_token","password","client_credentials","urn:ietf:params:oauth:grant-type:device_code","urn:openid:params:grant-type:ciba"],"acr_values_supported":["0","1"],"response_types_supported":["code","none","id_token","token","id_token token","code id_token","code token","code id_token token"],"subject_types_supported":["public","pairwise"],"id_token_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"id_token_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"id_token_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"userinfo_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512","none"],"userinfo_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"userinfo_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"request_object_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512","none"],"request_object_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"request_object_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"response_modes_supported":["query","fragment","form_post","query.jwt","fragment.jwt","form_post.jwt","jwt"],"registration_endpoint":"http://localhost:8080/realms/myrealm/clients-registrations/openid-connect","token_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"token_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"introspection_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"introspection_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"authorization_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"authorization_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"authorization_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"claims_supported":["aud","sub","iss","auth_time","name","given_name","family_name","preferred_username","email","acr"],"claim_types_supported":["normal"],"claims_parameter_supported":true,"scopes_supported":["openid","profile","roles","web-origins","phone","microprofile-jwt","acr","email","address","offline_access"],"request_parameter_supported":true,"request_uri_parameter_supported":true,"require_request_uri_registration":true,"code_challenge_methods_supported":["plain","S256"],"tls_client_certificate_bound_access_tokens":true,"revocation_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/revoke","revocation_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"revocation_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"backchannel_logout_supported":true,"backchannel_logout_session_supported":true,"device_authorization_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/auth/device","backchannel_token_delivery_modes_supported":["poll","ping"],"backchannel_authentication_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/ext/ciba/auth","backchannel_authentication_request_signing_alg_values_supported":["PS384","ES384","RS384","ES256","RS256","ES512","PS256","PS512","RS512"],"require_pushed_authorization_requests":false,"pushed_authorization_request_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/ext/par/request","mtls_endpoint_aliases":{"token_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/token","revocation_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/revoke","introspection_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/token/introspect","device_authorization_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/auth/device","registration_endpoint":"http://localhost:8080/realms/myrealm/clients-registrations/openid-connect","userinfo_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/userinfo","pushed_authorization_request_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/ext/par/request","backchannel_authentication_endpoint":"http://localhost:8080/realms/myrealm/protocol/openid-connect/ext/ciba/auth"}}`
7. The issuer value from the BFF configuration is: http://localhost:7080/auth/realms/myrealm
The issuer value as retrieved in line 130 of ClientRegistrations is: http://localhost:8080/realms/myrealm
These two lines are compared at line 131 of ClientRegistrations,
```
Assert.state(issuer.equals(metadataIssuer), () -> {
return "The Issuer \"" + metadataIssuer + "\" provided in the configuration metadata did not match the requested issuer \"" + issuer + "\"";
});
Because the two uris aren't equals, an exception is thrown:
Caused by: java.lang.IllegalStateException: The Issuer "http://localhost:8080/realms/myrealm" provided in the configuration metadata did not match the requested issuer "http://localhost:7080/auth/realms/myrealm"
at org.springframework.util.Assert.state(Assert.java:97) ~[spring-core-6.1.8.jar:6.1.8]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.withProviderConfiguration(ClientRegistrations.java:246) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:165) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.getBuilder(ClientRegistrations.java:216) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.fromIssuerLocation(ClientRegistrations.java:152) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.getBuilderFromIssuerIfPossible(OAuth2ClientPropertiesMapper.java:97) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.getClientRegistration(OAuth2ClientPropertiesMapper.java:71) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.lambda$asClientRegistrations$0(OAuth2ClientPropertiesMapper.java:65) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at java.base/java.util.HashMap.forEach(HashMap.java:1421) ~[na:na]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.asClientRegistrations(OAuth2ClientPropertiesMapper.java:64) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientRegistrationRepositoryConfiguration.clientRegistrationRepository(OAuth2ClientRegistrationRepositoryConfiguration.java:49) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.8.jar:6.1.8]
**Expected Behavior**
Given that the BFF pattern only masks the link of the authentication server, the two links return the same result, so an exception shouldn't be thrown
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- OS: [e.g. Windows]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional Context**
The solution here would be to change the issuer in the BFF configuration to the actual value of the issuer but this will defeat the purpose of using a Reverse-Proxy and thus is not a recommended solution. If would be best, instead of only comparing the links values, the results return by these links should be compared as well. That way if a Reverse-Proxy is used, the first option, comparing the links, will fail but the second option, comparing the results return by the links, will succeed and thus the two links should be marked equal
The text was updated successfully, but these errors were encountered:
Article and Module Links
https://github.com/eugenp/tutorials/blob/master/spring-security-modules/spring-security-oauth2-bff/backend/bff/src/main/resources/application.yml
Describe the Issue
When I try to use the BFF pattern with an OIDC authentication server, in my case Keycloak, I encounter a bug:
To Reproduce
Steps to reproduce the behavior:
#Keycloak configuration
scheme=http
hostname=localhost
reverse-proxy-port=7080
reverse-proxy-uri=${scheme}://${hostname}:${reverse-proxy-port}
authorization-server-prefix=/auth
issuer=${reverse-proxy-uri}${authorization-server-prefix}/realms/myrealm
client-id=myrealm-bff
client-secret=TrUt37XU00u2n0n30oW4isLiju2uG0wG
username-claim-json-path=$.preferred_username
authorities-json-path=$.realm_access.roles
bff-port=7081
bff-prefix=/bff
bff-uri=${scheme}://${hostname}:${bff-port}
resource-server-port=8083
audience=
Caused by: java.lang.IllegalStateException: The Issuer "http://localhost:8080/realms/myrealm" provided in the configuration metadata did not match the requested issuer "http://localhost:7080/auth/realms/myrealm"
at org.springframework.util.Assert.state(Assert.java:97) ~[spring-core-6.1.8.jar:6.1.8]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.withProviderConfiguration(ClientRegistrations.java:246) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:165) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.getBuilder(ClientRegistrations.java:216) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.security.oauth2.client.registration.ClientRegistrations.fromIssuerLocation(ClientRegistrations.java:152) ~[spring-security-oauth2-client-6.3.0.jar:6.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.getBuilderFromIssuerIfPossible(OAuth2ClientPropertiesMapper.java:97) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.getClientRegistration(OAuth2ClientPropertiesMapper.java:71) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.lambda$asClientRegistrations$0(OAuth2ClientPropertiesMapper.java:65) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at java.base/java.util.HashMap.forEach(HashMap.java:1421) ~[na:na]
at org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper.asClientRegistrations(OAuth2ClientPropertiesMapper.java:64) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientRegistrationRepositoryConfiguration.clientRegistrationRepository(OAuth2ClientRegistrationRepositoryConfiguration.java:49) ~[spring-boot-autoconfigure-3.3.0.jar:3.3.0]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.8.jar:6.1.8]
The text was updated successfully, but these errors were encountered: