Configure Spring Security OIDC/OAuth2 Behind a Gateway/Proxy - spring-boot

I have a problem on a Spring Boot microservice about the token decryption part in spring security. Basically the following problem occurs:
when calling the getSubject() method on #AuthenticationPrincipal Jwt jwt the following error occurs
Caused by: java.lang.IllegalStateException: The Issuer "https://ids-for-spid.aqp.it:443/oauth2/token" provided in the configuration did not match the requested issuer "https://clidens1.aqp.it:9443/oauth2/token"
I guess this is due to the following condition: in the well-known file there is an issuer with a different url base than the one passed to the library (I guess because there is a proxy or gateway), how could I solve the following problem?
Specifically, the url to access the well-known file is the following https://clidens1.aqp.it:9443/oauth2/token/.well-known/openid-configuration
ed and inside there is the following issuer https://ids-for-spid.aqp.it/oauth2/token, which differs from the base url clidens1.aqp.it on which I have the only accessibility.

During JWT validation, token iss claim is checked against the issuer URI in your conf. It must match exactly (even trailing slash is important if any).
For token validation, the Authorization server public key is also required. It is fetched using JWK-set URI, generally found in OIDC configuration, itself generally available from a location deduced from th iss claim value.
If the host declared in iss claim is not reachable from resource-server, have you tried to set JWK-set URI property too? Something like:
# this must be the exact iss claim value
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://clidens1.aqp.it:9443/oauth2/token
# actual value to use is the "jwks_uri" in https://clidens1.aqp.it:9443/oauth2/token/.well-known/openid-configuration
# with hostname and port reachable from resource-server (spring-app this properties file belongs to)
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://ids-for-spid.aqp.it:9443/oauth2/token/protocol/openid-connect/certs
If this hostname in the iss claim is not reachable by anyone, have you tried to configure your authorization-server to change the value of iss claim?
In Keycloak setting hostname configuration property would solve your problem, but you're obviously using another authorisation-server.

Related

JWT doesn't contain iss claim [duplicate]

This question already has answers here:
Iss claim not valid Keycloak
(2 answers)
Closed last month.
I'm using a Spring Boot application as a resource server, and it needs to validate the JWTs. But I'm always getting the following error on a request:
Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: The iss claim is not valid", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"
The issurer URI is set correct in the application.properties by the following line:
spring.security.oauth2.resourceserver.jwt.issuer-uri=<IssuerUri>
But I found out, that my JWT doesn't contain a claim which contains the issuer URI. Is there any way to override the validation for the issuer URI in Spring Boot?
I already tried to find a config in the WebSecurityConfigurerAdapter configurations to toggle the validation off. But I haven't found anything.
I think I found the configuration I was looking for. You can override the issuer uri from the JWT in the WebSecurityConfigurerAdapter
#Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2ResourceServer().jwt().jwkSetUri("<IssuerUri>");
}
If you are using Keycloak as Auth Server, this error can sometimes happen on local dev setup, when the Auth Server and Resource Server are running in a docker container, and the token was requested using the access token URL which points to localhost instead of the Auth Server's container name.
If you provide the host name of the access token url as localhost, Keycloak will add the iss claims to the token with the host as localhost, now when the resource server running in a container tries to validate the token against the Auth Server, it tries to contact it's own localhost instead of calling the AuthServer container.
The solution in this case, is to provide the container name as host name while requesting access token.
I explained this in detail in this video - youtu.be/5_EXMJbhLY4?t=2519

Iss claim not valid Keycloak

I use the keycloak service to login my web app. Use as a backend spring with oauth 2.0 security. When I go to make a request with postman using the bearer token obtained from keycloak it gives me an error 401 and also in the text of the answer next to the www-Authenticate entry it tells me:
Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: The iss claim is not valid", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1".
How could I solve this problem?
Spring config value must be exactly the same as iss claim value. Even trailing slash, if any, is important.
Do as #BenchVue wrote in comment: open one of access-token JWTs in jwt.io, copy iss claim value and paste it in spring conf.
the OAuth properties in application.properties must be the same as the Keycloak address:
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://keycloak-IP:Port/auth/realms/XXX

Invalid parameter "Invalid parameter: redirect_uri" Key cloak doesn't care what redirect URI I use

I want my Spring Boot app to leverage spring security and oath2 capabilities to authenticate using the a Keycloak server at https://auth.mycompanytest.com/
My initial attempt sends the user to:
https://auth.mycompanytest.com/auth/realms/MycompanyProfiling/protocol/openid-connect/auth?response_type=code&client_id=my-app&state=3fleTCJg4dBwJNjAnbkuq9m2Lwfm7_KwcOsOvO5k2nM%3D&redirect_uri=%22http://localhost:8080/login/oauth2/code/keycloak%22
Keycloak then says Invalid parameter: redirect_uri
I have tried these things for redirect_uri:
http://localhost:8080/*
https://mycompanytest.com/*
But it doesn't care.
Snippet of application.properties:
spring.security.oauth2.client.registration.keycloak.client-id= ${KEYCLOAK_CLIENT_ID}
spring.security.oauth2.client.registration.keycloak.client-secret= ${KEYCLOAK_CLIENT_SECRET}
spring.security.oauth2.client.registration.keycloak.provider=keycloak
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.redirect-uri="{baseUrl}/login/oauth2/code/keycloak"
spring.security.oauth2.client.provider.keycloak.token-uri=http://localhost:8080/auth/realms/MyRealm/protocol/openid-connect/token
spring.security.oauth2.client.provider.keycloak.authorization-uri=https://auth.mycompanytest.com/auth/realms/MyRealm/protocol/openid-connect/auth
spring.security.oauth2.client.provider.keycloak.user-info-uri= http://localhost:8080/auth/realms/MyRealm/protocol/openid-connect/userinfo
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.application.name=my-app
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/auth/realms/mycompany
*In the interest of privacy and anonymity I substitute MyCompany, MyRealm, MyApp (etc) in place of the real application. *
See redirect_uri parameter: %22http://localhost:8080/login/oauth2/code/keycloak%22. It is URL encoded value, so decoded value is "http://localhost:8080/login/oauth2/code/keycloak" - please note that you have " in the redirect URL so it can't match value, which you allowed in the client configuraton http://localhost:8080/*
I guess problem is your config:
spring.security.oauth2.client.registration.keycloak.redirect-uri="{baseUrl}/login/oauth2/code/keycloak"
I would try:
spring.security.oauth2.client.registration.keycloak.redirect-uri={baseUrl}/login/oauth2/code/keycloak
OR
spring.security.oauth2.client.registration.keycloak.redirect-uri=http://localhost:8080/login/oauth2/code/keycloak
Target is to remove quotes (%22) from the redirect_uri parameter.

Changing SSL Certificate and associated domain gives a 401 when it didn't before

I have an application with multiple services. One of them is the auth service that takes care of creating the jwt after checking that the client id (i.e. browser or app) is valid and provided username/password is also valid.
I have another service (gateway) that redirect to other services any requests from the users using the jwt token for authentication.
All this works and has been working for a few years. It is based on Spring Boot using Spring Security (starter v2.1.5). It is soon time to renew our certificate and at the same time move to our new domain. The new certificate has been applied to the Google Cloud Platform load balancer.
The call for health check using the Spring Actuator is responding with the proper "UP" (in json) response. When I try to make the call from same Postman request (with new domain name used) I get the following response with a 401 code:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
I do have the proper clientid and password/secrete encoded using base64 (hey it worked before and nothing else was changed).
I tried to debug setting #EnableWebSecurity(debug = true), but it generates zero logs from the request.
If I switch back the certificate to old one (and old domain), it works again without any other changes. This has been driving me a bit on the crazy side to say the least. Any help, suggestion, ideas would be appreciated.
It ended up being an error on my part. When I added a A class resources during the copy paste of Load Balancer IP, I put the same IP for both of my services (i.e. one of the copy didn't stick). Ending up in calling security on the gateway service when asking for the auth token.
Thanks for the comment #Boris-Treukhov

Owin AAD - required parameters for signature validation

I playing with webapi and trying to setup app configuration for proper signature validation in
WindowsAzureActiveDirectoryBearerAuthenticationOptions
I have noticed MetadataAddress field is not used in several examples online and in AAD auth samples: https://github.com/AzureADSamples/NativeClient-WebAPI-MultiTenant-WindowsStore/blob/master/TodoListServiceMT/App_Start/Startup.Auth.cs
When I launch the app I noticed there is a request to https://login.windows.net/common/federationmetadata/2007-06/federationmetadata.xml on app launch even though the field is not set. Is this the default value to MetadataAddress?
How does the signature validation work even though the sts address is
different in token?
How is the validation handled in case of custom sts service?
The tenant parameter passed in the option is enough for the middleware to determine the location of the metadata document of the corresponding Azure AD tenant. In the case of multitenant applications, as you observed that value is common. In the multitenant sample you can see that there is custom logic that takes over the verification of the issuer (what you called the "sts address" - that's more of an identifier). As you can see in the file that you linked, the options turn off the issuer validation via the switch ValidateIssuer = false. If you take a look at https://github.com/AzureADSamples/NativeClient-WebAPI-MultiTenant-WindowsStore/blob/master/TodoListServiceMT/AuthorizationFilters/MTAuthorizeAttribute.cs, you'll see that it executes logic meant to compare the issuer in the incoming token against a list of trusted issuer. Your own application might have different business logic for establishing whether the issuer of the incoming token should be trusted.

Resources