How to validate azureAd accessToken in Java

서인국님 0 Reputation points
2024-04-09T05:21:17.7766667+00:00

Hello. I wrote this article because I had a question while developing AzureAD.

The accessToken issued by AzureAD must be verified in JAVA. jwt, https://login.microsoftonline.com/" +tenantId + "/discovery/keys?appid=" + If you decode the clientId, the public key confirmed here is successfully received. When verified with the received public key, it returns false. How do I change it to return true in (boolean isVerified = jwsObject.verify(verifier);)? I attach the source below.

import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URL;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;

@Service
public class TokenValidatorService {

    @Value("${msal.tenant.id}")
    private String tenantId;

    @Value("${msal.client.id}")
    private String clientId;
    public boolean validateToken(String token) {
        try {
            URL jwkSetURL = new URL("https://login.microsoftonline.com/" + tenantId + "/discovery/keys?appid=" + clientId);

            JWKSet jwkSet = JWKSet.load(jwkSetURL);

            JWSObject jwsObject = JWSObject.parse(token);

            JWSAlgorithm algorithm = jwsObject.getHeader().getAlgorithm();
            if (!algorithm.equals(JWSAlgorithm.RS256)) {
                throw new IllegalArgumentException("No RS256");
            }

            RSAKey rsaKey = null;
            for (JWK jwk : jwkSet.getKeys()) {
                if (jwk.getKeyID().equals(jwsObject.getHeader().getKeyID())) {
                    rsaKey = (RSAKey) jwk;
                    break;
                }
            }
            if (rsaKey == null) {
                throw new IllegalArgumentException("No publicKey");
            }

            PublicKey publicKey = rsaKey.toRSAPublicKey();
            RSASSAVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);

            boolean isVerified = jwsObject.verify(verifier);
            return isVerified;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

Microsoft Security Microsoft Entra Other
{count} votes

2 answers

Sort by: Most helpful
  1. Navya 19,795 Reputation points Microsoft External Staff Moderator
    2024-04-11T06:54:11.1266667+00:00

    Hi @서인국님

    Thank you for posting this in Microsoft Q&A.

    I understand you query is related to validating Azure AD access tokens in java.

    Can you check exp and aud values in access token. It's possible that thejwsObject.verify(verifier) method is returning false because the token has expired or has been tampered with.The exp claim contains the expiration time of the token and the iss claim contains the issuer of the token.

    Below is the Sample code:

    public boolean validateToken(String token) {
        try {
            URL jwkSetURL = new URL("https://login.microsoftonline.com/" + tenantId + "/discovery/keys?appid=" + clientId);
            JWKSet jwkSet = JWKSet.load(jwkSetURL);
            JWSObject jwsObject = JWSObject.parse(token);
            JWSAlgorithm algorithm = jwsObject.getHeader().getAlgorithm();
            if (!algorithm.equals(JWSAlgorithm.RS256)) {
                throw new IllegalArgumentException("No RS256");
            }
            RSAKey rsaKey = null;
            for (JWK jwk : jwkSet.getKeys()) {
                if (jwk.getKeyID().equals(jwsObject.getHeader().getKeyID())) {
                    rsaKey = (RSAKey) jwk;
                    break;
                }
            }
            if (rsaKey == null) {
                throw new IllegalArgumentException("No publicKey");
            }
            PublicKey publicKey = rsaKey.toRSAPublicKey();
            RSASSAVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
            boolean isVerified = jwsObject.verify(verifier);
            if (!isVerified) {
                return false;
            }
            Date expirationTime = jwsObject.getPayload().getExpirationTime();
            if (expirationTime != null && expirationTime.before(new Date())) {
                return false;
            }
    
    
    

    For your reference: https://www.baeldung.com/java-jwt-check-expiry-no-exception

    Please let me know if you are facing any issue while executing code via comments section.

    Hope this helps. Do let us know if you any further queries.

    Thanks,

    Navya.


  2. Alptuğ Dingil 0 Reputation points
    2025-01-22T09:31:34.2+00:00
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.