-
I am trying to configure Azure Entra ID External in the setup based on BFF tutorial from Baeldung (https://www.baeldung.com/spring-cloud-gateway-bff-oauth2) Now I have this config in bff:
After successful login and redirect, the call to API is getting JWT of type designated for Microsoft Graph API (with nonce field in the header). My custom API fails to validate it and throw error: Signed JWT rejected: Invalid signature So I figured I probably need to create and use custom API scope instead so my backend API can validate it. However when I change the scope to contain only my custom application API scope: BFF Oauth2 client gets token and than fails with 401 UNAUTHORIZED from GET https://graph.microsoft.com/oidc/userinfo and redirect ends on error page with: An error occurred reading the UserInfo response: [invalid_user_info_response] What should be the correct approach here? Disable Oauth2 client to call userinfo? If so how can I achieve this? I would really appreciate advice how to get from here. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 1 reply
-
Hello and Thank you for you insights. My Openid configuration is https://119795fe-f178-444f-ae7a-14cbcc173d64.ciamlogin.com/119795fe-f178-444f-ae7a-14cbcc173d64/v2.0/.well-known/openid-configuration Oauth2 and Spring security is quite new for me so I'm learning on the go. I dig further into this and here are my findings: When I get access token for scopes We then send this access token to API/resource server when frontend do API call through bff. In the API the validation fails (as resource server has to validate it) as expected because this access token is not supposed to be used for custom APIs. Validation fails also at https://jwt.io To get a valid JWT ID token I figured out that I have to get access token for my custom API scope only Sources that refers to this issue: I was not able to figure out what is supposed to be the correct approach here and how to set it up (with spring security and/or spring-addons). I have thought of 2 possibilities:
I found there exists the spring boot starter for Entra ID spring-cloud-azure-starter-active-directory that possibly I hope may solve this issue but I was not able to get it working with spring-addons. I tried to disable spring.security.oauth2.client and enable instead spring.cloud.azure.active-directory, with no luck yet. |
Beta Was this translation helpful? Give feedback.
-
There are things I don't understand in Microsoft Entra ID and I opened a ticket. Two weeks ago, I asked why I want to authorize requests between an OAuth2 confidential client and some OAuth2 resource servers using Microsoft Entra ID as an OpenID provider. My OAuth2 client is a Spring Cloud Gateway instance configured with authorization code and refresh token flows. It is a "confidential" client (uses a client-id and a client secret). It expects the authorization server to comply with OIDC. My OAuth2 resource servers are Spring REST APIs validating Bearer access tokens using a JWT decoder. All expect the authorization server to issue JWT access tokens and to comply with OIDC. When I write "comply with OIDC" I mean:
What I managed to do so far:
What does not work:
What behaves differently than I expect:
|
Beta Was this translation helpful? Give feedback.
-
Microsoft Entra ID looks like an OIDC Provider, but doesn't satisfy the OIDC discovery and OpenID tokens specifications for V1 tokens (which is the default for Entra apps). To switch to V2 tokens, edit the manifest to set This can be done under Another option is to disable OIDC discovery and issuer validation during tokens validation (leave Sample configuration setting neither oauth2-client-id: 561973cf-b7bc-4db7-856d-c2a2d6c5a1fa
oauth2-client-secret: change-me
tenant: 4f68014f-7f14-4f89-8197-06f0b3ff24d9
spring:
security:
oauth2:
client:
provider:
entra:
authorization-uri: https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize
token-uri: https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token
jwk-set-uri: https://login.microsoftonline.com/${tenant}/discovery/v2.0/keys
registration:
bff:
provider: entra
redirect-uri: http://localhost:7080/login/oauth2/code/quiz-bff
client-id: ${oauth2-client-id}
client-secret: ${oauth2-client-secret}
authorization-grant-type: authorization_code
scope:
- openid
- api://561973cf-b7bc-4db7-856d-c2a2d6c5a1fa/quiz
com:
c4-soft:
springaddons:
oidc:
ops:
- jwk-set-uri: ${spring.security.oauth2.client.provider.entra.jwk-set-uri}
authorities:
- path: $.roles With, as explained in "Is iss configuration property mandatory?", this @Configuration
@EnableMethodSecurity
public class WebSecurityConfig {
@Component
public class FirstOpenidProviderPropertiesResolver implements OpenidProviderPropertiesResolver {
private final Optional<OpenidProviderProperties> opProperties;
public FirstOpenidProviderPropertiesResolver(SpringAddonsOidcProperties properties) {
this.opProperties = properties.getOps().isEmpty() ? Optional.empty()
: Optional.of(properties.getOps().get(0));
}
@Override
public Optional<OpenidProviderProperties> resolve(Map<String, Object> claimSet) {
return opProperties;
}
}
} |
Beta Was this translation helpful? Give feedback.
-
@ch4mpy, I have an additional question related to this. I have a similar setup in a project I inherited (I'm not using springaddons though). I also use Azure AD in my spring security configuration. Locally everything works. However, when I deploy to kubernetes, I still have issues. On kubernetes I have an Ingress controller that serves as a load balancer/reverse proxy. When I try to access a secured endpoint when I'm NOT logged in, I'm not redirected to the microsoft login page. Instead I get a timeout. My BFF is running in a separate pod, so my setup is this:
In my logging I see the following: So, I'm redirected to my load balancer (and the request times out after that). |
Beta Was this translation helpful? Give feedback.
Microsoft Entra ID looks like an OIDC Provider, but doesn't satisfy the OIDC discovery and OpenID tokens specifications for V1 tokens (which is the default for Entra apps).
To switch to V2 tokens, edit the manifest to set
api.requestedAccessTokenVersion: 2
.This can be done under
Applications
->App registrations
->{appName}
->Manifest
->Microsoft Graph App Manifest (New)
Another option is to disable OIDC discovery and issuer validation during tokens validation (leave
issuer-uri
andiss
empty in properties). But this is pretty dirty and I'd rather advise using something else than a Microsoft authorization server, or hiding it behind an actual OIDC Provider if you can't do without.Samp…