【问题标题】:Validating Azure AD JWT id_token in Java在 Java 中验证 Azure AD JWT id_token
【发布时间】:2017-03-31 05:06:48
【问题描述】:

我正在尝试验证我在 AD 服务器上成功进行用户授权后收到的 RS256 令牌。

我正在查看响应的 id_token 属性值。

这就是我所拥有的 -

String[] split_string = idToken.split("\\.");
String base64EncodedHeader = split_string[0];
String base64EncodedBody = split_string[1];
String base64EncodedSignature = split_string[2];
Base64 base64Url = new Base64(true);
String header = new String(base64Url.decode(base64EncodedHeader));
JSONObject jsonObjHeader = JSONObject.fromObject(header);
String body = new String(base64Url.decode(base64EncodedBody));
JSONObject jsonObjBody = JSONObject.fromObject(body);
String signatre = new String(base64Url.decode(base64EncodedSignature));

//kid for signature validation
String kid = jsonObjHeader.getString("kid");

//open-id-config endpoint
String openIdConfigEndPoint = "https://login.microsoftonline.com/{tenantID}/.well-known/openid-configuration";
OAuthRequest requestOpenId = constructOAuthRequest(
                    openIdConfigEndPoint, oauthNonce, oauthTimestamp, Verb.GET);
Response responseOpenId = requestOpenId.send();
String openIdString = responseOpenId.getBody();
JSONObject jsonObjopenId = JSONObject.fromObject(openIdString);

String keysEndPoint = jsonObjopenId.getString("jwks_uri");
OAuthRequest requestkeysEndPoint = constructOAuthRequest(keysEndPoint,
                    oauthNonce, oauthTimestamp, Verb.GET);
Response responsekeysEndPoint = requestkeysEndPoint.send();
String keysEndPointString = responsekeysEndPoint.getBody();
JSONObject jsonKeysEndPointString = JSONObject.fromObject(keysEndPointString);

JSONArray keysEndPointArray = jsonKeysEndPointString.getJSONArray("keys");
String x5t = null;
String n = null;
String e = null;        
for (int i = 0; i < keysEndPointArray.size(); i++) {
    JSONObject obj1 = keysEndPointArray.getJSONObject(i);
    if (obj1.getString("kid").equals(kid)) {

        n = obj1.getString("n");
        e = obj1.getString("e");
        x5t = obj1.getString("x5t");                
    }

}

byte[] modulusBytes = Base64.decodeBase64(n.getBytes("UTF-8"));
byte[] exponentBytes = Base64.decodeBase64(e.getBytes("UTF-8"));

BigInteger modulusInt = new BigInteger(1, modulusBytes);
BigInteger exponentInt = new BigInteger(1, exponentBytes);

try {
    Signature signature = Signature.getInstance("SHA256withRSA");
    RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(modulusInt, exponentInt);

    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey pubKey = keyFactory.generatePublic(publicSpec);

    signature.initVerify(pubKey);
    signature.update(base64Url.decode(base64EncodedBody));

    boolean isVerified = signature.verify(base64Url .decode(base64EncodedSignature));
    // isVerified is false , should be true on successful validation
} catch (Exception ex) {
    ex.printStackTrace();
}

//trying with JJWT


try {
    KeyFactory factory = KeyFactory.getInstance("RSA");
    PublicKey pub = factory.generatePublic(publicSpec);
    Jwt<Header, String> c = Jwts.parser().setSigningKey(pub).parsePlaintextJwt(idToken);
    System.out.println();
} catch (Exception e1) {
    e1.printStackTrace();
}

这是我得到的例外 -

io.jsonwebtoken.SignatureException: Unable to verify RSA signature using configured PublicKey. Signature length not correct: got 255 but was expecting 256
    at io.jsonwebtoken.impl.crypto.RsaSignatureValidator.isValid(RsaSignatureValidator.java:50)
    at io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator.isValid(DefaultJwtSignatureValidator.java:47)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:339)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:458)
    at io.jsonwebtoken.impl.DefaultJwtParser.parsePlaintextJwt(DefaultJwtParser.java:480)
    at edu.umn.faip.web.spring.controller.OAuthSSOTestController.referenceData(OAuthSSOTestController.java:221)
    at org.springframework.web.servlet.mvc.SimpleFormController.referenceData(SimpleFormController.java:214)
    at org.springframework.web.servlet.mvc.AbstractFormController.showForm(AbstractFormController.java:574)
    at org.springframework.web.servlet.mvc.SimpleFormController.showForm(SimpleFormController.java:198)
    at org.springframework.web.servlet.mvc.SimpleFormController.showForm(SimpleFormController.java:175)
    at org.springframework.web.servlet.mvc.AbstractFormController.showNewForm(AbstractFormController.java:338)
    at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:278)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.security.SignatureException: Signature length not correct: got 255 but was expecting 256
    at sun.security.rsa.RSASignature.engineVerify(Unknown Source)
    at java.security.Signature$Delegate.engineVerify(Unknown Source)
    at java.security.Signature.verify(Unknown Source)
    at io.jsonwebtoken.impl.crypto.RsaSignatureValidator.doVerify(RsaSignatureValidator.java:63)
    at io.jsonwebtoken.impl.crypto.RsaSignatureValidator.isValid(RsaSignatureValidator.java:47)
    ... 38 more

我已尝试为此使用 jjwt 库,但这似乎也不起作用。我试图从端点上发布的公钥中获取模数和指数,以在 java 中构造我自己的密钥对象,然后使用它来验证签名。

非常感谢任何帮助!

【问题讨论】:

  • 请详细说明“似乎不起作用”。最好带有错误消息或其他一些预期与观察到的操作。
  • @JoeC 你是指使用java安全验证,还是使用jjwt?
  • 您想选择两者中的哪一个。如果您没有偏好,两者都可以。
  • 对于 java 安全代码,isVerified 变量为假,理想情况下应该为真,因为令牌是有效的。那就是问题所在。对于 JJWT,我将只修改帖子以包含我得到的异常。

标签: java active-directory oauth-2.0 authorization azure-active-directory


【解决方案1】:

你可以试试

signature.update((split_string[0]+ "." +  
                  split_string[0]).getBytes(StandardCharsets.UTF_8)); 

OpenID Connect - how to verify id token in Java?

你可以参考这个链接。它对我有用。

【讨论】:

  • 请添加一些解释。
猜你喜欢
  • 2017-08-25
  • 2020-07-08
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
  • 2017-09-25
  • 2016-12-02
  • 1970-01-01
  • 2017-11-22
相关资源
最近更新 更多