【问题标题】:Receiving invalid access token from Azure AD从 Azure AD 接收无效访问令牌
【发布时间】:2021-12-26 01:00:25
【问题描述】:

我正在开发一个包含以下组件的应用程序:

  • API (ASP.NET Core)
  • 网站
  • 移动应用 (Xamarin.Forms)

用户已通过 Azure AD 进行身份验证,并且应收到持有者令牌以访问 API。对于网页,这按预期工作,但我似乎无法让它为移动应用程序工作。

我可以使用 Microsoft.identity.Client 库进行身份验证,并且确实收到了访问令牌。但是,此访问令牌不起作用,因为使用此令牌调用 API 返回 401 Unauthorized,并带有响应标头:

Www-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"
  • 当我使用硬编码在移动应用中的 web 应用中的不记名令牌时,它可以工作。
  • 当我比较这两个令牌时,我发现移动应用检索到的令牌是 v1 令牌,而不是 web 应用收到的 v2 令牌。

在 Azure 应用注册中,我注册了所有 3 个组件,并授予了网站和移动应用的 API 权限。

在移动应用中验证和获取访问令牌:

var app = PublicClientApplicationBuilder.Create(clientId)
    .WithRedirectUri("msal116d9cbe-88ef-4b73-bae2-0d21c10df305://auth")
    .WithIosKeychainSecurityGroup(this.configuration.IOSKeychainSecurityGroup)
    .WithB2CAuthority("https://testorganisation.b2clogin.com/tfp/testorganisation.onmicrosoft.com/B2C_1_SignupSignin/")
            .Build();

var scopes = new string[]
{
    "openid",
    "email",
    "https://testorganisation.onmicrosoft.com/api/access_as_user"
}

var accounts = await this.app
    .GetAccountsAsync()

await this.app
    .AcquireTokenSilent(scopes, accounts.FirstOrDefault())
    .ExecuteAsync()

来自 Azure 的 API 应用注册清单:

{
    "id": "b003da59-5a76-4083-99e6-bdb708feae16",
    "acceptMappedClaims": null,
    "accessTokenAcceptedVersion": 2,
    "addIns": [],
    "allowPublicClient": true,
    "appId": "9bf40874-747a-41d5-a3fe-2d0b1a3fcfa8",
    "appRoles": [],
    "oauth2AllowUrlPathMatching": false,
    "createdDateTime": "2021-10-27T08:32:35Z",
    "certification": null,
    "disabledByMicrosoftStatus": null,
    "groupMembershipClaims": null,
    "identifierUris": [
        "https://testorganisation.onmicrosoft.com/api"
    ],
    "informationalUrls": {
        "termsOfService": null,
        "support": null,
        "privacy": null,
        "marketing": null
    },
    "keyCredentials": [],
    "knownClientApplications": [],
    "logoUrl": null,
    "logoutUrl": null,
    "name": "testorganisation API",
    "oauth2AllowIdTokenImplicitFlow": false,
    "oauth2AllowImplicitFlow": false,
    "oauth2Permissions": [
        {
            "adminConsentDescription": "Access the testorganisation API as a user",
            "adminConsentDisplayName": "Access testorganisation API as user",
            "id": "1e8c2b96-7b60-4a32-9145-1083e1fba86b",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "type": "Admin",
            "userConsentDescription": null,
            "userConsentDisplayName": null,
            "value": "access_as_user"
        },
        {
            "adminConsentDescription": "Access the API as administrator",
            "adminConsentDisplayName": "Access testorganisation API as admin",
            "id": "63a54831-11a2-47f2-8e50-2872f1c25d5d",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "type": "Admin",
            "userConsentDescription": null,
            "userConsentDisplayName": null,
            "value": "access_as_admin"
        }
    ],
    "oauth2RequirePostResponse": false,
    "optionalClaims": null,
    "orgRestrictions": [],
    "parentalControlSettings": {
        "countriesBlockedForMinors": [],
        "legalAgeGroupRule": "Allow"
    },
    "passwordCredentials": [],
    "preAuthorizedApplications": [],
    "publisherDomain": "testorganisation.onmicrosoft.com",
    "replyUrlsWithType": [
        {
            "url": "https://localhost:5001/swagger/oauth2-redirect.html",
            "type": "Spa"
        }
    ],
    "requiredResourceAccess": [
        {
            "resourceAppId": "00000003-0000-0000-c000-000000000000",
            "resourceAccess": [
                {
                    "id": "37f7f235-527c-4136-accd-4a02d197296e",
                    "type": "Scope"
                },
                {
                    "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
                    "type": "Scope"
                }
            ]
        }
    ],
    "samlMetadataUrl": null,
    "signInUrl": null,
    "signInAudience": "AzureADandPersonalMicrosoftAccount",
    "tags": [
        "notApiConsumer",
        "webApi"
    ],
    "tokenEncryptionKeyId": null
}

来自 Azure 的移动应用注册清单:

{
    "id": "1cc5a0bc-13dc-4101-9cff-ace48ad4865d",
    "acceptMappedClaims": null,
    "accessTokenAcceptedVersion": 2,
    "addIns": [],
    "allowPublicClient": true,
    "appId": "116d9cbe-88ef-4b73-bae2-0d21c10df305",
    "appRoles": [],
    "oauth2AllowUrlPathMatching": false,
    "createdDateTime": "2021-01-13T19:37:49Z",
    "certification": null,
    "disabledByMicrosoftStatus": null,
    "groupMembershipClaims": null,
    "identifierUris": [],
    "informationalUrls": {
        "termsOfService": null,
        "support": null,
        "privacy": null,
        "marketing": null
    },
    "keyCredentials": [],
    "knownClientApplications": [],
    "logoUrl": null,
    "logoutUrl": null,
    "name": "testorganisation Mobile App",
    "oauth2AllowIdTokenImplicitFlow": false,
    "oauth2AllowImplicitFlow": false,
    "oauth2Permissions": [],
    "oauth2RequirePostResponse": false,
    "optionalClaims": null,
    "orgRestrictions": [],
    "parentalControlSettings": {
        "countriesBlockedForMinors": [],
        "legalAgeGroupRule": "Allow"
    },
    "passwordCredentials": [],
    "preAuthorizedApplications": [],
    "publisherDomain": "testorganisation.onmicrosoft.com",
    "replyUrlsWithType": [
        {
            "url": "msal116d9cbe-88ef-4b73-bae2-0d21c10df305://auth",
            "type": "InstalledClient"
        }
    ],
    "requiredResourceAccess": [
        {
            "resourceAppId": "9bf40874-747a-41d5-a3fe-2d0b1a3fcfa8",
            "resourceAccess": [
                {
                    "id": "1e8c2b96-7b60-4a32-9145-1083e1fba86b",
                    "type": "Scope"
                }
            ]
        },
        {
            "resourceAppId": "00000003-0000-0000-c000-000000000000",
            "resourceAccess": [
                {
                    "id": "37f7f235-527c-4136-accd-4a02d197296e",
                    "type": "Scope"
                },
                {
                    "id": "7427e0e9-2fba-42fe-b0c0-848c9e6a8182",
                    "type": "Scope"
                }
            ]
        }
    ],
    "samlMetadataUrl": null,
    "signInUrl": null,
    "signInAudience": "AzureADandPersonalMicrosoftAccount",
    "tags": [
        "apiConsumer",
        "mobileApp"
    ],
    "tokenEncryptionKeyId": null
}

【问题讨论】:

标签: c# xamarin.forms azure-active-directory jwt msal


【解决方案1】:

• 很明显,即使在将“accessTokenAcceptedVersion”配置为 2(从移动应用程序的应用清单代码中可以看出)之后,您在移动应用程序上接收到的是 v1 访问令牌而不是 v2 访问令牌,而同样的情况并未发生用于网络应用 API。因此,请使用下面的示例代码来使用参数“AcquireTokenOnBehalfOf”,以便作为 v2 令牌传递给 Web 应用程序并正确解码的令牌也将传递给移动应用程序 API 并被正确识别。因此,请相应地更新您的 msal.net 代码以调用移动应用程序 api,如下所示:-

需要的 MSAL.net 代码

    ‘ string[] scopes = { "user.read" };
        string accesstoken = "";

        string appKey = "yor web api client secret";
        string clientId = "your web api application id";

        var app = ConfidentialClientApplicationBuilder.Create(clientId)
          .WithClientSecret(appKey)
          .Build();
        UserAssertion userAssertion = new UserAssertion(accesstoken, 
     "urn:ietf:params:oauth:grant-type:jwt-bearer");
        var result = app.AcquireTokenOnBehalfOf(scopes, 
      userAssertion).ExecuteAsync().Result;
        Console.WriteLine(result.AccessToken); ‘

'AcquireTokenOnBehalfOf'的这个参数肯定是缺失的,因为传递给移动应用程序的令牌被认为是v1而不是v2。另外,请检查移动应用 API 的范围应该是“user_impersonification”。

请参考以下链接:-

https://github.com/Azure-Samples/ms-identity-aspnet-webapi-onbehalfof

【讨论】:

  • 该示例显示了一个 ConfidentalClientApplication,它与 AcquireTokenOnBehalfOf 方法一起在移动应用等公共客户端应用程序中无法使用
  • 请尝试将 '.default' 附加到应用资源 URI,然后再次检查。
  • 也尝试提供资源 URI 作为范围。
  • 感谢您的宝贵时间。我尝试使用范围"openid", "email", "https://testorganisation.onmicrosoft.com/api/.default",但这根本没有给我访问令牌,我尝试了"openid", "email", "https://testorganisation.onmicrosoft.com/api/access_as_user", "https://testorganisation.onmicrosoft.com/api/.default,这给了我相同的 v1 令牌结构
  • 嗨@Daan,您可以参考这个stackover流程线程以获取参考和更多详细信息-stackoverflow.com/questions/54368394/…
猜你喜欢
  • 2019-08-31
  • 2020-12-21
  • 2019-05-15
  • 1970-01-01
  • 2021-01-21
  • 2020-07-05
  • 1970-01-01
  • 2023-03-23
  • 2018-08-17
相关资源
最近更新 更多