我已经编写了一个JAX-RS ContainerRequestFilter来在一组REST服务上实现基于JWT的访问控制,但应用程序无法解码JWT id_token。
我的web客户端成功执行Azure AD登录过程,并返回JWT id_token,然后请求并接收JWT access_token。
在我的服务器上,我正在使用https://github.com/auth0/java-jwt库解码id_token,但调用
DecodedJWT jwtIdent = JWT.decode(identificationHeader);
毫无例外地失败。
我有一个简单的Java程序,它在web服务器上对相同id_token的String版本执行相同的JWT.decode(id_toke)调用,对的调用运行良好。
来自客户端的http请求对象是:
var request = {
method: 'POST',
url: url,
headers: {
'Content-Type': 'application/json;charset=utf-8',
'Authorization': "Bearer " + $scope.tokens.accessToken,
'Identification': $scope.tokens.idToken
}
};
ContainerRequestFilter的顶部如下:
public void filter(ContainerRequestContext requestContext) throws IOException {
logger.info("public void filter(ContainerRequestContext requestContext) - Begin");
// Get the HTTP Authorization header from the request
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
String identificationHeader = requestContext.getHeaderString(IDENTIFICATION_PROPERTY);
try {
Method method = resourceInfo.getResourceMethod();
logger.info("REST Method Called: " + method.getName());
// Is access allowed for all?
if( ! method.isAnnotationPresent(PermitAll.class)) {
// Is access denied for all?
if(method.isAnnotationPresent(DenyAll.class)) {
logger.info("Method: " + method.getName() + " has protections " + DenyAll.class.getName());
logger.info("ACCESS_FORBIDDEN");
requestContext.abortWith(ACCESS_FORBIDDEN);
return;
}
if (authorizationHeader == null) {
logger.info(HttpHeaders.AUTHORIZATION + " = <null>");
requestContext.abortWith(BAD_REQUEST);
}
if (identificationHeader == null) {
logger.info(IDENTIFICATION_PROPERTY +" = <null>");
requestContext.abortWith(BAD_REQUEST);
}
logger.info("IdentificationHeader: n <" + identificationHeader + ">nn");
DecodedJWT jwtIdent = JWT.decode(identificationHeader);
对JWT.decode(…)的调用发生了,但从未返回,客户端返回一个"500"错误代码。
当令牌到达服务器时,我可以System.out.println(…)它们看起来很好。我可以将它们粘贴到我的另一个Java应用程序中,它们解码良好,在https://jwt.io/.
当UTF-8数据从客户端传输到服务器时,我还需要做些什么来保护它的完整性吗?
经过进一步调查,我发现authorizationHeader和identificationHeader值实际上并没有像我预期的那样进行Base64编码。
我删除了对JWT.decode()的调用,然后将identificationHeader的内容拆分为一个句点('.'),该句点返回三个JWT组件。然后,我可以简单地将其中一个字符串解析为JSON,并检索必要的JWT声明。