如何解决使用特定于租户的端点或将应用程序配置为多租户
我正在将Spring Boot应用程序从ADAL迁移到MSAL。
我收到如下所示的错误:
java.util.concurrent.ExecutionException: com.microsoft.aad.msal4j.MsalServiceException:
AADSTS50194: Application 'fd0ac989-0246-4999-b562-6d42d3636c22'(primadollardev_solanapi) is not configured as a multi-tenant application.
Usage of the /common endpoint is not supported for such applications created after '10/15/2018'.
Use a tenant-specific endpoint or configure the application to be multi-tenant.
Trace ID: 49905cdc-df8e-4bbb-9f48-daa2fe893000
Correlation ID: d6957f88-b418-4351-b141-4a5fbb6c6a99
Timestamp: 2020-08-30 06:05:40Z
ADAL代码
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for
* license information.
*/
package com.microsoft.azure.spring.autoconfigure.aad;
import com.microsoft.aad.adal4j.ClientCredential;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.proc.BadJOSEException;
import com.nimbusds.jose.util.ResourceRetriever;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.naming.ServiceUnavailableException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.ParseException;
import java.util.concurrent.ExecutionException;
public class AADAuthenticationFilter extends OncePerRequestFilter {
private static final Logger log = LoggerFactory.getLogger(AADAuthenticationFilter.class);
private static final String CURRENT_USER_PRINCIPAL = "CURRENT_USER_PRINCIPAL";
private static final String CURRENT_USER_PRINCIPAL_GRAPHAPI_TOKEN = "CURRENT_USER_PRINCIPAL_GRAPHAPI_TOKEN";
private static final String CURRENT_USER_PRINCIPAL_JWT_TOKEN = "CURRENT_USER_PRINCIPAL_JWT_TOKEN";
private static final String TOKEN_HEADER = "Authorization";
private static final String TOKEN_TYPE = "Bearer ";
private AADAuthenticationProperties aadAuthProps;
private ServiceEndpointsProperties serviceEndpointsProps;
private UserPrincipalManager principalManager;
public AADAuthenticationFilter(AADAuthenticationProperties aadAuthProps,ServiceEndpointsProperties serviceEndpointsProps,ResourceRetriever resourceRetriever) {
this.aadAuthProps = aadAuthProps;
this.serviceEndpointsProps = serviceEndpointsProps;
this.principalManager = new UserPrincipalManager(serviceEndpointsProps,aadAuthProps,resourceRetriever,false);
}
@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException,IOException {
final String authHeader = request.getHeader(TOKEN_HEADER);
if (authHeader != null && authHeader.startsWith(TOKEN_TYPE)) {
try {
final String idToken = authHeader.replace(TOKEN_TYPE,"");
UserPrincipal principal = (UserPrincipal) request
.getSession().getAttribute(CURRENT_USER_PRINCIPAL);
String graphApiToken = (String) request
.getSession().getAttribute(CURRENT_USER_PRINCIPAL_GRAPHAPI_TOKEN);
final String currentToken = (String) request
.getSession().getAttribute(CURRENT_USER_PRINCIPAL_JWT_TOKEN);
final ClientCredential credential =
new ClientCredential(aadAuthProps.getClientId(),aadAuthProps.getClientSecret());
final AzureADGraphClient client =
new AzureADGraphClient(credential,serviceEndpointsProps);
if (principal == null ||
graphApiToken == null ||
graphApiToken.isEmpty() ||
!idToken.equals(currentToken)
) {
principal = principalManager.buildUserPrincipal(idToken);
final String tenantId = principal.getClaim().toString();
graphApiToken = client.acquireTokenForGraphApi(idToken,tenantId).getAccessToken();
principal.setUserGroups(client.getGroups(graphApiToken));
request.getSession().setAttribute(CURRENT_USER_PRINCIPAL,principal);
request.getSession().setAttribute(CURRENT_USER_PRINCIPAL_GRAPHAPI_TOKEN,graphApiToken);
request.getSession().setAttribute(CURRENT_USER_PRINCIPAL_JWT_TOKEN,idToken);
}
final Authentication authentication = new PreAuthenticatedAuthenticationToken(
principal,null,client.convertGroupsToGrantedAuthorities(principal.getUserGroups()));
authentication.setAuthenticated(true);
log.info("Request token verification success. {}",authentication);
SecurityContextHolder.getContext().setAuthentication(authentication);
} catch (MalformedURLException | ParseException | BadJOSEException | JOSEException ex) {
log.error("Failed to initialize UserPrincipal.",ex);
throw new ServletException(ex);
} catch (ServiceUnavailableException | InterruptedException | ExecutionException ex) {
log.error("Failed to acquire graph api token.",ex);
throw new ServletException(ex);
}
}
filterChain.doFilter(request,response);
}
}
MSAL代码
public class MSALAuthenticationFilter extends OncePerRequestFilter {
private static final Logger log = LoggerFactory.getLogger(MSALAuthenticationFilter.class);
private static final String TOKEN_HEADER = "Authorization";
private static final String TOKEN_TYPE = "Bearer ";
// Properties from the application.properties file like clientId,tenant and stuff.
private static final String CURRENT_USER_PRINCIPAL = "CURRENT_USER_PRINCIPAL";
private static final String CURRENT_USER_ACCESS_TOKEN = "CURRENT_USER_ACCESS_TOKEN";
@Override
protected void doFilterInternal(HttpServletRequest request,IOException {
final String authHeader = request.getHeader(TOKEN_HEADER);
UserPrincipal principal = (UserPrincipal) request.getSession().getAttribute(CURRENT_USER_PRINCIPAL);
if (authHeader != null && authHeader.startsWith(TOKEN_TYPE)) {
try {
final String idToken = authHeader.replace(TOKEN_TYPE,"");
ConfidentialClientApplication clientApplication = ConfidentialClientApplication.builder(
clientId,ClientCredentialFactory.create(clientSecret))
.authority(authority)
.build();
Set<String> scopes = new HashSet<>(Arrays.asList(scope.split(" ")));
UserAssertion assertion = new UserAssertion(idToken);
OnBehalfOfParameters params = OnBehalfOfParameters.builder(scopes,assertion).build();
CompletableFuture<AuthenticationResult> future = clientApplication.acquireToken(params);
AuthenticationResult accessToken = future.get();
if (principal == null) {
principal = principalManager.buildUserPrincipal(idToken,accessToken);
request.getSession().setAttribute(CURRENT_USER_PRINCIPAL,principal);
request.getSession().setAttribute(CURRENT_USER_ACCESS_TOKEN,accessToken);
}
final Authentication authentication = new PreAuthenticatedAuthenticationToken(
principal,convertGroupsToGrantedAuthorities(principal.getUserGroups()));
authentication.setAuthenticated(true);
log.info("Request token verification success. {}",authentication);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
catch (MalformedURLException | InterruptedException | ExecutionException ex) {
log.error("Failed to authenticate",ex);
throw new ServletException(ex);
}
}
filterChain.doFilter(request,response);
}
}
请给我一个解决方案...
解决方法
这似乎是版本问题,请参考此GitHub issue。请更新您的版本为2.2.4。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。