我希望我的Identity Server 4服务器为某些已注册的客户端提供附加服务(例如"MyAdditionalService"
)。该服务将由他们通过在服务器上定义的自定义端点来使用。
我正在考虑为我的服务定义一个API(例如,命名为" myAdditionalService"),以便可以根据客户的配置授予客户端对此类服务的访问权限。但是我不确定如何限制对端点的访问(MVC - Action方法),只允许允许使用API的客户端(可能代表用户)。
我发现我能做到:
services.AddAuthorization(options =>
{
options.AddPolicy("MyAdditionalServicePolicy",
policy => policy.RequireClaim("scope",
"myAdditionalService"));
});
并使用属性[Authorize("MyAdditionalServicePolicy")]
来修饰用于访问此类服务的操作方法。但是,我不知道服务器可以同时是API还是即使可能。
我该如何实现?令人困惑的是,令牌服务也扮演着API的角色,因为它可以保护对动作方法或端点的访问。
感谢。
更新:
我的网络应用程序是IdentityServerWithAspNetIdentity,它已经使用了Asp.net核心身份的身份验证机制。为了这个例子,我的网络应用程序如果向某些注册客户提供的附加服务是用户的Twitter好友列表(建模在名为Twitter的控制器上,名为ImportFriends的行为),因此api被称为" TwitterFriends& #34;
根据以下回复中的建议,我将Configure()
方法修改为app.UseJwtBearerAuthentication()
。我已经有app.UseIdentity()
和app.UseIdentityServer()
,如下所示:
app.UseIdentity();
app.UseIdentityServer();
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AuthenticationScheme = "Bearer",
Authority = Configuration["BaseUrl"],
Audience = "TwitterFriends",
RequireHttpsMetadata = false //TODO: make true, it is false for development only
});
// Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
app.UseGoogleAuthentication(new GoogleOptions
{
AuthenticationScheme = "Google",
SignInScheme = "Identity.External", // this is the name of the cookie middleware registered by UseIdentity()
在专用控制器上:
[Authorize(ActiveAuthenticationSchemes = "Identity.Application,Bearer")]
//[Authorize(ActiveAuthenticationSchemes = "Identity.Application")]
//[Authorize(ActiveAuthenticationSchemes = "Bearer")]
[SecurityHeaders]
public class TwitterController : Controller
{...
但是我在日志中得到了这个:
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware
[7]
Identity.Application was not authenticated. Failure message: Unprotect tic
ket failed
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.A
uthorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
Executing ChallengeResult with authentication schemes (Identity.Applicatio
n, Bearer).
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware
[12]
AuthenticationScheme: Identity.Application was challenged.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[12]
AuthenticationScheme: Bearer was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action IdentityServerWithAspNetIdentity.Controllers.TwitterContro
ller.ImportFriends (IdentityServerWithAspNetIdentity) in 86.255ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 105.2844ms 401
我尝试了不同的属性组合,但似乎Identity.Application和Bearer在这种情况下并不相处:获得401.
任何帮助表示赞赏。 感谢..
答案 0 :(得分:3)
请参阅此示例,了解如何在与IdentityServer相同的Web应用程序中托管API。
https://github.com/brockallen/IdentityServerAndApi
实质上,您需要添加JWT令牌验证处理程序:
services.AddAuthentication()
.AddJwtBearer(jwt =>
{
jwt.Authority = "base_address_of_identityserver";
jwt.Audience = "name of api";
});
在API本身上,您必须选择JWT身份验证方案:
public class TestController : ControllerBase
{
[Route("test")]
[Authorize(AuthenticationSchemes = "Bearer")]
public IActionResult Get()
{
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToArray();
return Ok(new { message = "Hello API", claims });
}
}
如果要强制执行其他授权策略,可以将其传递到[Authorize]属性或强制调用它。
答案 1 :(得分:0)
要实现此目的,首先必须编写一些策略。策略将定义该特定api的可访问性范围。 因此,您将某些范围分配给注册的客户。假设范围名称是“ ApiOnlyForRegisteredClients”。
因此,我们将如下创建策略:
services.AddAuthorization(options =>
{
options.SetRegisteredClientsPolicy();
}
和
private static void RequireScope(this AuthorizationPolicyBuilder authorizationPolicyBuilder, string[] values)
{
authorizationPolicyBuilder.RequireClaim("scope", values);
}
private static void SetRegisteredClientsPolicy(this AuthorizationOptions options)
{
options.AddPolicy(
OpenIdPolicies.Clients.RegisteredClients,
policyBuilder =>
{
policyBuilder.RequireAuthenticatedUser();
policyBuilder.RequireScope(new string[] { "ApiOnlyForRegisteredClients" });
});
}
完成后,就完成了策略创建。
确保在创建访问令牌时,将相同的值“ ApiOnlyForRegisteredClients”放在范围声明中。
现在,我们必须添加一个api并使用[Authorize]属性对其进行标签。
[Authorize(AuthenticationSchemes = "Bearer", Policy = OpenIdPolicies.Clients.RegisteredClients)]
public async Task<ActionResult<T>> Post(int userId, [FromBody] List<int> simRoleIds)
{
}
现在我们必须添加jwt身份验证中间件。
.AddJwtBearer("Bearer", options =>
{
options.Authority = configuration["AuthorityAddresses"];
options.RequireHttpsMetadata = Convert.ToBoolean(configuration["RequireHttpsMetadata"]);
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
TokenDecryptionKey = new X509SecurityKey()
ValidAudiences = apiResources.Select(x => x.ResourceName).ToList(),
ValidIssuers = new List<string> { authorityAddressWithHttps.Uri.OriginalString, authorityAddressWithBasePathHttps.Uri.OriginalString, configuration["AuthorityAddresses"] }
};
})