【问题标题】:OpenIddict get token_id before responseOpenIddict 在响应前获取 token_id
【发布时间】:2018-04-05 04:12:07
【问题描述】:
[AllowAnonymous]
[HttpPost("~/api/auth/login")]
[Produces("application/json")]
public async Task<IActionResult> Login(OpenIdConnectRequest request)
{
  ...
      var ticket = await CreateTicketAsync(request, user);
      _logger.LogInformation($"User logged in (id: {user.Id})");

      // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.

      return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}

OpenIddict 在调用 SignIn 方法后创建令牌对吗?在发送响应之前如何访问创建的 refresh_token token_id?

我想将 token_id 与自定义 device_id 关联并保存到数据库。然后我将允许用户使用指定的设备撤销 refresh_token。

【问题讨论】:

  • 无法在生成令牌标识符之前检索它。也就是说,我将更新令牌管理器以允许从令牌存储中检索您存储在票证中的身份验证属性,这将允许您做您想做的事情。公开版本准备好后,我会通知您。

标签: c# asp.net-core openiddict


【解决方案1】:

以下是如何使用最新的 RC2 包(您可以在 MyGet 提要中找到)。

1) 创建从内置实体派生的自定义实体:

public class MyApplication : OpenIddictApplication<string, MyAuthorization, MyToken>
{
    public MyApplication() => Id = Guid.NewGuid().ToString();
}

public class MyAuthorization : OpenIddictAuthorization<string, MyApplication, MyToken>
{
    public MyAuthorization() => Id = Guid.NewGuid().ToString();
}

public class MyScope : OpenIddictScope<string>
{
    public MyScope() => Id = Guid.NewGuid().ToString();
}

public class MyToken : OpenIddictToken<string, MyApplication, MyAuthorization>
{
    public MyToken() => Id = Guid.NewGuid().ToString();

    public string DeviceId { get; set; }
}

2) 更新您的授权控制器以将设备标识符存储为身份验证属性:

// ...
var ticket = new AuthenticationTicket(principal, properties,
    OpenIdConnectServerDefaults.AuthenticationScheme);

ticket.SetProperty("device_id", "[the device identifier]");
// ...

3) 创建自定义令牌管理器并覆盖PopulateAsync 方法以将设备标识符附加到存储在数据库中的令牌条目:

public class MyManager : OpenIddictTokenManager<MyToken>
{
    public MyManager(
        IOpenIddictTokenStore<MyToken> store,
        ILogger<OpenIddictTokenManager<MyToken>> logger)
        : base(store, logger)
    {
    }

    protected override Task PopulateAsync(MyToken token, OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken)
    {
        if (descriptor.Properties.TryGetValue("device_id", out var identifier))
        {
            token.DeviceId = identifier;
        }

        return base.PopulateAsync(token, descriptor, cancellationToken);
    }
}

4) 更新您的 Startup 类以使用新实体和自定义管理器:

services.AddDbContext<ApplicationDbContext>(options =>
{
    // ...
    options.UseOpenIddict<MyApplication, MyAuthorization, MyScope, MyToken, string>();
});

services.AddOpenIddict<MyApplication, MyAuthorization, MyScope, MyToken>(options =>
{
    // ...
    options.AddTokenManager<MyManager>();
});

【讨论】:

  • 这种方法对于新版本是否仍然相同,还是从那时起发生了变化?我还需要在发送 SignInResult 之前获取令牌。
  • 它在 1.0 和 2.0 RTM 中仍然有效,但在 3.0 中不受支持,因为它将不再使用 AuthenticationTicketAuthenticationProperties。此外,在返回 SignInResult 之前您无法获取令牌,因为它正是触发授权响应并在后台创建令牌的原因。您在那个阶段需要令牌是否有特殊原因?
  • 嗨,凯文,感谢您的快速回复!我目前使用的是 2.0.1 版本,我需要它将 OpenIdConnectResponse 转换为自定义 DTO。如果您说在响应之前无法获取令牌,那么也许我可以使用 AOP 或响应过滤器。
  • 根据您需要返回自定义 DTO 的原因,可能会有更好的选择。是返回自定义属性吗?
  • 不一定是自定义属性。我正在使用为OpenIdConnectResponse 生成打字稿模型的 swagger codegen,它具有例如属性accessToken。但是来自服务器的响应具有 access_token 的这个特殊属性(注意下划线)。因此,如果我在响应之前映射到自定义 DTO,我可以解决这种映射不一致问题。
猜你喜欢
  • 2016-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 2021-05-07
  • 1970-01-01
相关资源
最近更新 更多