对多租户应用程序使用授权码流不起作用

Posted

技术标签:

【中文标题】对多租户应用程序使用授权码流不起作用【英文标题】:Using Authorization Code flow for a multi tenant app not working 【发布时间】:2021-01-06 18:51:38 【问题描述】:

我有 2 个 microsoft tenat AD 租户 A 和 Tenat B,

我需要通过在租户 A 下注册的应用程序为租户 B 调用 Azure API(如 azure 资源配置、读取 azure 数据、调用成本 API 和其他一些 azure API)。我已通过以下方式实现了这一点。

    在租户 A 下创建了一个多租户应用(仅具有图形 API 权限)。

    使用此 URL 通过授权代码流(租户 B 用户(不是管理员)同意租户 A 应用程序)获取 azure 刷新令牌

https://login.microsoftonline.com/common/oauth2/authorize?client_id=&response_mode=form_post&response_type=code&redirect_url=authscope=openid&state=297e2e0374a6cbfb0174a73dcfce0755&nonce=c6234c0c-ab14-49f4-aa41-827061841d61

    成功重定向后,我收到了刷新令牌。

    当我尝试使用该刷新令牌获取“https://management.azure.com”的访问令牌时,出现以下错误。

com.microsoft.aad.adal4j.AuthenticationException: "error_description":"AADSTS65001: 用户或管理员未同意使用 ID 为 '801e6372-f223-4acb-895c-c966a0ff57c6' 的应用程序名为 'AnkitTestMFAApp'。为此用户和资源发送交互式授权请求。\r\n跟踪 ID: 0ec48b06-64cf-47ed-b5d7-8725fba91600\r\n相关 ID: 96d78b24-5442-469a-a798-0f1eace171c1\r\n时间戳: 2020-09- 20 12:41:09Z","错误":"invalid_grant" 在 com.microsoft.aad.adal4j.AdalTokenRequest.executeOAuthRequestAndProcessResponse(AdalTokenRequest.java:129) 在 com.microsoft.aad.adal4j.AuthenticationContext.acquireTokenCommon(AuthenticationContext.java:930) 在 com.microsoft.aad.adal4j.AcquireTokenCallable.execute(AcquireTokenCallable.java:70) 在 com.microsoft.aad.adal4j.AcquireTokenCallable.execute(AcquireTokenCallable.java:38) 在 com.microsoft.aad.adal4j.AdalCallable.call(AdalCallable.java:47) 在 java.util.concurrent.FutureTask.run(未知来源) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(未知来源) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(未知来源) 在 java.lang.Thread.run(未知来源) 我正在使用 com.microsoft.azure.credentials.AzureTokenCredentials 类来获取令牌。

即使我使用任何 azure java sdk 函数

AzureTokenCredentials 凭据 = 我们自定义的 AzureTokenCredentials 实现 Azure azure = Azure.authenticate(credentials).withSubscription(cloudAccount.getSubscriptionId());

AzureTokenCredentials 的自定义实现

@覆盖 public AuthenticationResult getAccessTokenByRefreshToken(StringtenantId, String resource, String refreshToken, 字符串clientId,字符串clientSecret) 抛出 ExecutionException、InterruptedException、MalformedURLException 身份验证上下文 authContext; 身份验证结果 authResult; ExecutorService 服务 = null; 未来的未来;

    try 
        service = Executors.newFixedThreadPool(1);
        authContext = new AuthenticationContext(MessageFormat.format("0/1", "https://login.microsoftonline.com", tenantId), true,
                service);

        future = authContext.acquireTokenByRefreshToken(refreshToken, new ClientCredential(clientId, clientSecret),
                resource, null);

        authResult = future.get();

        return authResult;
     finally 
        if (service != null) 
            service.shutdown();
        
    

我可以在我的租户 B 企业应用程序列表下看到此应用程序的服务原则条目。

可能的问题是什么?应该如何解决?

Asking for admin approval

App Permissions

Consent user settings

Conditional Access details

Consent settings

Added Permissions As Low Risk section

【问题讨论】:

如果我的答案对您有帮助,您可以接受它作为答案(点击答案旁边的复选标记,将其从灰色切换为已填充。)。见meta.stackexchange.com/questions/5234/…。这对其他社区成员可能是有益的。谢谢。 【参考方案1】:

这是因为租户 B 用户(不是管理员)不同意应用程序的范围 https://management.azure.com

以下是修复它的步骤。

删除租户 B 中的企业应用程序,将撤销同意。

在租户 A 的 Azure AD 应用中添加权限 https://management.azure.com/user_impersonation

使用以下字符串获取代码,然后刷新令牌。当您使用租户 B 用户进行用户同意时,您需要同意https://management.azure.com/user_impersonation 权限。

https://login.microsoftonline.com/common/oauth2/authorize?client_id=your client id&response_mode=query&response_type=code&redirect_url=https://localhost/&scope=openid https://management.azure.com/.default&state=297e2e0374a6cbfb0174a73dcfce0755&nonce=c6234c0c-ab14-49f4-aa41-827061841d61

这次刷新令牌将生效,因为您会在您的租户 B 企业应用程序中找到 https://management.azure.com/user_impersonation 权限。

【讨论】:

评论不用于扩展讨论;这个对话是moved to chat。

以上是关于对多租户应用程序使用授权码流不起作用的主要内容,如果未能解决你的问题,请参考以下文章

设置套接字流不起作用

libgdx 中的音乐流不起作用(JAVA)

WSO2 EI 6.3.0 - Jms,vfs,mailto和本地传输在除carbon.super之外的任何租户中都不起作用

Laravel Nova 多态多对多关系不起作用

NSFetchedResultsController 和多对多关系不起作用

Sequelize多态多对多 - `add` mixin不起作用