如何使用WindowsAzureActiveDirectoryBearerAuthentication来验证令牌

本文关键字:验证 令牌 WindowsAzureActiveDirectoryBearerAuthentication 何使用 | 更新日期: 2023-09-27 18:11:56

我正在遵循以下GitHub示例来跨WebApp和WebApi实现身份验证机制。

https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet

我正在对 WebApp 和 WebAPI 使用单个应用注册,获取"https://abc.onmicrosoft.com/App"的访问令牌并将其传递给 WebApi。我正在将令牌附加到名为"持有者"的 HTTPS 标头。我在 WebApi Owin 启动类中有以下内容来验证受众和租户的令牌,但实际上并没有按预期验证这些令牌。

几个问题:1. 什么触发以下处理程序来验证租户和受众的令牌?是控制器类上的 [授权] 属性吗?2. 如何找到执行处理程序的令牌?3. 将"保存登录令牌"设置为 true 将保存令牌。如何从此令牌检索令牌以及获取图形 API 的访问令牌?

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
              new WindowsAzureActiveDirectoryBearerAuthenticationOptions
              {
                  Tenant = "abc.onmicrosoft.com",
                  TokenValidationParameters = new TokenValidationParameters
                  {
                      ValidAudience = "https://abc.onmicrosoft.com/App",
                      SaveSigninToken = true,
                  }
              });

请指教。提前感谢!

如何使用WindowsAzureActiveDirectoryBearerAuthentication来验证令牌

什么触发以下处理程序来验证租户和受众的令牌?

默认情况下,中间件以Active模式运行,因此它将尝试在每个请求中查找令牌。如果找到一个,它将尝试验证它。如果发现它有效,则会创建一个可在其他 OWIN 中间件和 Web API 组件中访问的ClaimsPrincipal

它还会下载公钥,用于从 Azure AD 在应用启动时检查令牌签名。如果您使用像 Fiddler 这样的工具,您可以看到这一点。

如何在哪里找到执行处理程序的令牌?

不确定我是否理解这个问题,我希望我上面的回答澄清了这个过程。

将 SaveSigninToken 设置为 true 将保存令牌。如何从此令牌检索令牌以及获取图形 API 的访问令牌?

您尝试做的是使用 on-behalf-of 流调用 API。您可以在此处找到示例应用:https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof。更具体地说,您应该对这部分感兴趣:https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof/blob/master/TodoListService/Controllers/TodoListController.cs#L133。

        ClientCredential clientCred = new ClientCredential(clientId, appKey);
        var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
        string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
        string userAccessToken = bootstrapContext.Token;
        UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
        string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
        string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        AuthenticationContext authContext = new AuthenticationContext(authority, new DbTokenCache(userId));
        // In the case of a transient error, retry once after 1 second, then abandon.
        // Retrying is optional.  It may be better, for your application, to return an error immediately to the user and have the user initiate the retry.
        bool retry = false;
        int retryCount = 0;
        do
        {
            retry = false;
            try
            {
                result = await authContext.AcquireTokenAsync(graphResourceId, clientCred, userAssertion);
                accessToken = result.AccessToken;
            }
            catch (AdalException ex)
            {
                if (ex.ErrorCode == "temporarily_unavailable")
                {
                    // Transient error, OK to retry.
                    retry = true;
                    retryCount++;
                    Thread.Sleep(1000);
                }
            }
        } while ((retry == true) && (retryCount < 1));

控制器中的 [授权] 修饰或我们指定的任何方法都会触发 Owin 安全处理程序来验证令牌并生成声明。