同一 ASP.NET 核心 API 中的 Azure AD 客户端凭据和交互
Azure AD Client Credentials and Interactive in same ASP.NET Core API
我有一个 ASP.NET Core (3.1) web API 和几个客户端 UI 应用程序。通过 Azure AD 进行身份验证,一切正常,使用:
services.AddAuthentication()
.AddAzureADBearer(options => Configuration.Bind("AzureAD", options))
我还想使用客户端凭据流程允许机器对机器 API 访问。我也可以使用相同的应用程序注册使它正常工作。
但是,我需要一种方法来验证请求正在使用哪个流,因为我想使用客户端凭据 API 向 API 请求公开我不希望交互式用户使用的功能可以访问。
完成这项工作的最佳方法是什么?
我在 AAD 中创建了一个单独的应用程序注册,客户端凭据授予的客户端密码已打开,我让它向令牌添加权限(作为角色)。在 API 的应用程序注册中,我已授予客户端凭据应用程序注册权限。但是,如果我通过此流程获得令牌,则无法进行身份验证。我发现更改令牌请求中的范围以匹配 API 应用程序注册的范围会给我一个允许我访问 API 的令牌,但它会丢失应用程序角色。
一个交互式令牌有一些用户特定的声明。因此,一种解决方法是检查这些声明是否存在,如果它们存在,则禁止我想要限制的功能,但这似乎有点老套。
我还能做什么?有没有办法使两个登录流程都有效?或者我错过的另一个选择?
万一其他人需要让它工作,我通过切换来让它工作:
services.AddAuthentication()
.AddAzureADBearer(options => Configuration.Bind("AzureAD", options))
至:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.MetadataAddress = $"https://login.microsoftonline.com/mydomain.onmicrosoft.com/.well-known/openid-configuration";
options.TokenValidationParameters.ValidateAudience = false;
});
如问题中所述,还有一些额外的步骤。我在 AAD 中创建了一个单独的应用程序注册,并在应用程序注册中为 API 授予了新应用程序注册的权限。在新的应用程序注册中,我必须编辑清单以获得我想要作为角色包含的范围(范围仅分配给用户令牌,而不是通过客户端凭据授予获得的令牌)。
使用具有角色数据的令牌,对于对我的受限端点的请求,我可以检查它是否存在:
public bool ValidateScope(string scopeName)
{
return _httpContextAccessor.HttpContext.User.IsInRole(scopeName);
}
bool authorised = _clientCredentialsService.ValidateScope("restricted");
if (!authorised)
{
throw new UnauthorizedAccessException("Attempt to access restricted functionality as a regular user");
}
(我有一个过滤器可以检测到这个异常并将其作为 403 冒泡给消费者)。
如果其他人正在这样做,您可以看到我已将 ValidateAudience
设置为 false,因此如果您这样做,您可能想要添加一些政策。
我有一个 ASP.NET Core (3.1) web API 和几个客户端 UI 应用程序。通过 Azure AD 进行身份验证,一切正常,使用:
services.AddAuthentication()
.AddAzureADBearer(options => Configuration.Bind("AzureAD", options))
我还想使用客户端凭据流程允许机器对机器 API 访问。我也可以使用相同的应用程序注册使它正常工作。
但是,我需要一种方法来验证请求正在使用哪个流,因为我想使用客户端凭据 API 向 API 请求公开我不希望交互式用户使用的功能可以访问。
完成这项工作的最佳方法是什么?
我在 AAD 中创建了一个单独的应用程序注册,客户端凭据授予的客户端密码已打开,我让它向令牌添加权限(作为角色)。在 API 的应用程序注册中,我已授予客户端凭据应用程序注册权限。但是,如果我通过此流程获得令牌,则无法进行身份验证。我发现更改令牌请求中的范围以匹配 API 应用程序注册的范围会给我一个允许我访问 API 的令牌,但它会丢失应用程序角色。
一个交互式令牌有一些用户特定的声明。因此,一种解决方法是检查这些声明是否存在,如果它们存在,则禁止我想要限制的功能,但这似乎有点老套。
我还能做什么?有没有办法使两个登录流程都有效?或者我错过的另一个选择?
万一其他人需要让它工作,我通过切换来让它工作:
services.AddAuthentication()
.AddAzureADBearer(options => Configuration.Bind("AzureAD", options))
至:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.MetadataAddress = $"https://login.microsoftonline.com/mydomain.onmicrosoft.com/.well-known/openid-configuration";
options.TokenValidationParameters.ValidateAudience = false;
});
如问题中所述,还有一些额外的步骤。我在 AAD 中创建了一个单独的应用程序注册,并在应用程序注册中为 API 授予了新应用程序注册的权限。在新的应用程序注册中,我必须编辑清单以获得我想要作为角色包含的范围(范围仅分配给用户令牌,而不是通过客户端凭据授予获得的令牌)。
使用具有角色数据的令牌,对于对我的受限端点的请求,我可以检查它是否存在:
public bool ValidateScope(string scopeName)
{
return _httpContextAccessor.HttpContext.User.IsInRole(scopeName);
}
bool authorised = _clientCredentialsService.ValidateScope("restricted");
if (!authorised)
{
throw new UnauthorizedAccessException("Attempt to access restricted functionality as a regular user");
}
(我有一个过滤器可以检测到这个异常并将其作为 403 冒泡给消费者)。
如果其他人正在这样做,您可以看到我已将 ValidateAudience
设置为 false,因此如果您这样做,您可能想要添加一些政策。