Как проверить токен Azure AD JWT в Java? - PullRequest
1 голос
/ 27 марта 2020

У меня есть Azure AD JWT-токен, полученный с помощью библиотеки Msal, но когда я пытаюсь проверить этот токен, что-то не так:

Клиент: веб-часть Sharepoint

 const config = {
     auth: {
         clientId: "xxxxx",
         authority: "https://login.microsoftonline.com/yyyyyy"
     }
 };

 const myMSALObj = new UserAgentApplication(config);

 let accessTokenRequest = {
     scopes: ["user.read"],
     loginHint: this.context.pageContext.user.loginName,
     extraQueryParameters: {domain_hint: 'organizations'}
 }

 myMSALObj.acquireTokenSilent(accessTokenRequest).then(
  function(accessTokenResponse) { 
  // Acquire token silent success 
  let accessToken = accessTokenResponse.accessToken;

Я пытаюсь получить открытый ключ из: https://login.microsoftonline.com/tenant-id/.well-known/openid-configuration, но с помощью этого открытого ключа c я никогда не смогу перенаправить на: https://login.microsoftonline.com/common/discovery/keys

Есть ли другой способ получить ключ publi c в этом случае?

Сервер: Проверка

public PublicKey getPublicKeyFromParams(String e, String n){

    byte[] modulusBytes = Base64.getUrlDecoder().decode(n);

    BigInteger modulusInt = new BigInteger(1, modulusBytes);

    byte[] exponentBytes = Base64.getUrlDecoder().decode(e);

    BigInteger exponentInt = new BigInteger(1, exponentBytes);

    KeyFactory keyFactory;

    RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(modulusInt, exponentInt);

        try {

            keyFactory = KeyFactory.getInstance("RSA");

            return keyFactory.generatePublic(publicSpec);

        } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {

            ex.printStackTrace();

        }

    return null;

}

@Test

public void name() throws Exception {

    String jwt = "xxxxxxx";

    KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256);

    String e = Base64.getUrlEncoder().encodeToString((((RSAPublicKeyImpl) keyPair.getPublic()).getPublicExponent()).toByteArray());

    String n = Base64.getUrlEncoder().encodeToString((((RSAPublicKeyImpl) keyPair.getPublic()).getModulus()).toByteArray());

    System.out.println("Public Key: " + Base64.getUrlEncoder().encodeToString(keyPair.getPublic().getEncoded()));

    System.out.println("Public Key Exponent: " + e);

    System.out.println("Public Key Modulus: " + n);

    String jws = Jwts.builder().setSubject("pepe").signWith(keyPair.getPrivate()).compact();

    System.out.println("Generated JWS:" + jws);

    PublicKey publicKey = getPublicKeyFromParams(e, n);

    Jwt parsedJWs = Jwts.parserBuilder().setSigningKey(publicKey).build().parse(jws);

    System.out.println("Parsed JWS: " + parsedJWs);

    publicKey = getPublicKeyFromParams(eValue, nValue);

    System.out.println("Azure PublicKey fron n-e: " + publicKey);

    CertificateFactory factory = CertificateFactory.getInstance("X.509");

    Certificate cert = factory.generateCertificate(new ByteArrayInputStream(

    DatatypeConverter.parseBase64Binary("cccccccccccccccccc")));

    publicKey = cert.getPublicKey();

    System.out.println("Azure PublicKey from x5c: " + publicKey);

    Jwt jwtParsed = Jwts.parserBuilder().setSigningKey(publicKey).build().parse(jwt);

    System.out.println(jwtParsed);

}

public static PublicKey getPublicKey(String key){

    try{

        byte[] byteKey = Base64.getDecoder().decode(key);

        X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);

        KeyFactory kf = KeyFactory.getInstance("RSA");

        return kf.generatePublic(X509publicKey);

    }

    catch(Exception e){

        e.printStackTrace();

    }

    return null;

}

С уважением

Ответы [ 2 ]

0 голосов
/ 01 апреля 2020

Наконец, я нашел решение.

С этим изменением проверка работает нормально.

let accessTokenRequest = {
    scopes:["clientId/.default"],
    loginHint: this.context.pageContext.user.loginName,
    extraQueryParameters: {domain_hint: 'organizations'}
}

С уважением!

0 голосов
/ 31 марта 2020

если вы хотите проверить Azure токен доступа AD, мы можем попытаться использовать sdk java-jwt и jwks-rsa для его реализации.

Например

  1. Установить SDK через maven
 <dependency>
      <groupId>com.microsoft.azure</groupId>
      <artifactId>azure-storage</artifactId>
      <version>8.6.2</version>
    </dependency>

    <dependency>
      <groupId>com.auth0</groupId>
      <artifactId>jwks-rsa</artifactId>
      <version>0.11.0</version>
    </dependency>

Код

a. проверить подпись

 String token="<your AD token>";
  DecodedJWT jwt = JWT.decode(token);
  System.out.println(jwt.getKeyId());

  JwkProvider provider = null;
  Jwk jwk =null;
  Algorithm algorithm=null;

  try {
      provider = new UrlJwkProvider(new URL("https://login.microsoftonline.com/common/discovery/keys"));
      jwk = provider.get(jwt.getKeyId());
      algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
      algorithm.verify(jwt);// if the token signature is invalid, the method will throw SignatureVerificationException
  } catch (MalformedURLException e) {
      e.printStackTrace();
  } catch (JwkException e) {
      e.printStackTrace();
  }catch(SignatureVerificationException e){

     System.out.println(e.getMessage());

  }
...