不要使用OpenIddict接收刷新令牌

时间:2017-10-10 17:29:40

标签: c# asp.net-core token refresh-token openiddict

我有一个基于.net core 2.0的web api项目。

我非常关注http://kevinchalet.com/2017/01/30/implementing-simple-token-authentication-in-aspnet-core-with-openiddict/上非常好的例子。

返回auth的SignIn()结果的代码。方法如下:

if (request.IsPasswordGrantType())
{
    // (...)
    if (useraccount != null && useraccount.Failcount <= AppConstants.AuthMaxAllowedFailedLogin)
    {
        var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role);

        identity.AddClaim(OpenIdConnectConstants.Claims.Subject, AppConstants.AuthSubjectClaim, OpenIdConnectConstants.Destinations.AccessToken);
        identity.AddClaim(OpenIdConnectConstants.Claims.Name, useraccount.Username, OpenIdConnectConstants.Destinations.AccessToken);

        return SignIn(new ClaimsPrincipal(identity), OpenIdConnectServerDefaults.AuthenticationScheme);
    }
    // (...)
}

我的启动代码如下:

services.AddDbContext<DbContext>(options =>
{
    options.UseInMemoryDatabase(nameof(DbContext));
    options.UseOpenIddict();
});

services.AddOpenIddict(options =>
{
    options.AddEntityFrameworkCoreStores<DbContext>();
    options.AddMvcBinders();
    options.EnableTokenEndpoint(DcpConstants.ApiTokenRoute);
    options.AllowPasswordFlow();
    options.AllowRefreshTokenFlow();
    options.SetAccessTokenLifetime(TimeSpan.FromHours(1));
    options.SetRefreshTokenLifetime(TimeSpan.FromDays(1));
    options.DisableHttpsRequirement();
});

services.AddAuthentication(options =>
{
    options.DefaultScheme = OAuthValidationDefaults.AuthenticationScheme;
}).AddOAuthValidation();

现在,当我发送带有以下参数的帖子请求时:

username: foo@bar.com
password: myPassword
grant_type: password
scope: openid profile offline_access

我只收到范围,token_type,access_token,expires_in和id_token,没有refresh_token。

我错过了什么?

2 个答案:

答案 0 :(得分:4)

OAuth2规范肯定允许使用密码返回刷新令牌,因此OpenIddict完全支持。

对于OpenIddict返回的刷新令牌,您必须在调用offline_access时授予特殊的SignIn范围。 E.g:

if (request.IsPasswordGrantType())
{
    // (...)
    if (useraccount != null && useraccount.Failcount <= AppConstants.AuthMaxAllowedFailedLogin)
    {
        var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role);

        identity.AddClaim(OpenIdConnectConstants.Claims.Subject, AppConstants.AuthSubjectClaim, OpenIdConnectConstants.Destinations.AccessToken);
        identity.AddClaim(OpenIdConnectConstants.Claims.Name, useraccount.Username, OpenIdConnectConstants.Destinations.AccessToken);

        var ticket = new AuthenticationTicket(
            new ClaimsPrincipal(identity),
            new AuthenticationProperties(),
            OpenIdConnectServerDefaults.AuthenticationScheme);

        // You have to grant the 'offline_access' scope to allow
        // OpenIddict to return a refresh token to the caller.
        ticket.SetScopes(OpenIdConnectConstants.Scopes.OfflineAccess);

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

请注意,您还必须处理控制器中的grant_type=refresh_token个请求。以下是使用Identity:https://github.com/openiddict/openiddict-samples/blob/dev/samples/RefreshFlow/AuthorizationServer/Controllers/AuthorizationController.cs#L75-L109

的示例

答案 1 :(得分:0)

  

options.AllowPasswordFlow();

刷新令牌不能与密码流一起使用,因为在此流程中用户永远不会被重定向到在Auth服务器上登录并且so can’t directly authorize the application

  

如果应用程序使用用户名密码OAuth身份验证流程,则不会发出刷新令牌,因为用户无法在此流程中授权应用程序。如果访问令牌过期,则使用用户名密码OAuth流的应用程序必须重新验证用户身份。