nabeelh21
nabeelh21

Reputation: 83

Microsoft Graph SDK for Java - InvalidAuthenticationToken error 80049217

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:

enter image description here

app.module: import { OAuthModule } from 'angular-oauth2-oidc'; enter image description here

app.component.ts enter image description here

Postman: enter image description here

Upvotes: 1

Views: 1749

Answers (1)

Allen Wu
Allen Wu

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.

enter image description here

A sample for your reference.

Upvotes: 2

Related Questions