Reputation: 83
My Authorization Client: Angular, Resource Server: Java Spring Boot, Authorization Server: Azure Active Directory
I am using oAuth2 to login via Angular via the PKCE Authorization Flow and then pass the token to the back end. I am able to access the token in my back end via the Authorization Beaer Header, but when I go to use that token to access Microsoft Graph API, I am getting an Invalid token exception.
com.microsoft.graph.http.GraphServiceException: Error code: InvalidAuthenticationToken Error message: CompactToken parsing failed with error code: 80049217
I am not sure why it is causing this error, because its valid and I can verify via https://jwt.io/ and access my other protected api in postman with the token.
AuthProvider.java
public class AuthProvider implements IAuthenticationProvider {
private String accessToken = null;
public AuthProvider(String accessToken) {
this.accessToken = accessToken;
}
@Override
public void authenticateRequest(IHttpRequest request) {
// Add the access token in the Authorization header
request.addHeader("Authorization", "Bearer " + accessToken);
}
}
SecurityConfiguration.java
http.cors().and()
.authorizeRequests().antMatchers("/home").permitAll()
.and()
.authorizeRequests().antMatchers("/actuator/health").permitAll()
.and()
.authorizeRequests().antMatchers("/**").authenticated()
.and()
.oauth2ResourceServer().jwt();
GraphAPIController.java
private static IGraphServiceClient graphClient = null;
private static AuthProvider authProvider = null;
private static void ensureGraphClient(String accessToken) {
if (graphClient == null) {
// Create the auth provider
authProvider = new AuthProvider(accessToken);
// Create default logger to only log errors
DefaultLogger logger = new DefaultLogger();
logger.setLoggingLevel(LoggerLevel.ERROR);
// Build a Graph client
graphClient = GraphServiceClient
.builder()
.authenticationProvider(authProvider)
.logger(logger)
.buildClient();
}
}
@GetMapping("/getUser")
public static User getUser(@RequestHeader(value="Authorization") String token) {
System.out.println("THE TOKEN: " +token);
ensureGraphClient(token);
// GET /me to get authenticated user
User me = graphClient
.me()
.buildRequest()
.get();
System.out.println("THE USER: " + me);
return me;
}
My Angular Setup:
app.module:
import { OAuthModule } from 'angular-oauth2-oidc';
Upvotes: 1
Views: 1749
Reputation: 16438
An access token can only be for one resource. I can see that you configure scope: 'openid api://{appid}/app'
in your Angular Setup. It means the access token is for this resource api://{appid}/app
rather than Microsoft Graph https://graph.microsoft.com
. That is why you got the InvalidAuthenticationToken Error.
So if you want to call Microsoft Graph in your backend API, you need to consider OAuth 2.0 On-Behalf-Of flow. The OAuth 2.0 On-Behalf-Of flow (OBO) serves the use case where an application invokes a service/web API, which in turn needs to call another service/web API.
In your case, your backend API is web API A and Microsoft Graph is web API B.
A sample for your reference.
Upvotes: 2