Identity Server 4上的授权客户端的自定义端点

时间:2017-09-19 14:16:38

标签: identityserver4

我希望我的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.

任何帮助表示赞赏。 感谢..

2 个答案:

答案 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"] }
       };
   })