不使用 OpenIddict 接收刷新令牌
Do not receive refresh token with OpenIddict
我有一个基于 .net core 2.0 的网络 api 项目。
我几乎遵循了 http://kevinchalet.com/2017/01/30/implementing-simple-token-authentication-in-aspnet-core-with-openiddict/ 上的非常好的示例。
returns 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();
现在,当我发送带有以下参数的 post 请求时:
username: foo@bar.com
password: myPassword
grant_type: password
scope: openid profile offline_access
我只收到范围,token_type、access_token、expires_in 和 id_token,没有 refresh_token。
我错过了什么?
options.AllowPasswordFlow();
刷新令牌不能与密码流程一起使用,因为在此流程中用户永远不会被重定向到 Auth Server 登录,so can’t directly authorize the application:
If the application uses the username-password OAuth authentication flow, no refresh token is issued, as the user cannot authorize the application in this flow. If the access token expires, the application using username-password OAuth flow must re-authenticate the user.
OAuth2 规范绝对允许使用密码返回刷新令牌,因此,OpenIddict 完全支持。
对于 OpenIddict 返回的刷新令牌,您必须在调用 SignIn
时授予特殊的 offline_access
范围。例如:
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
我有一个基于 .net core 2.0 的网络 api 项目。
我几乎遵循了 http://kevinchalet.com/2017/01/30/implementing-simple-token-authentication-in-aspnet-core-with-openiddict/ 上的非常好的示例。
returns 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();
现在,当我发送带有以下参数的 post 请求时:
username: foo@bar.com
password: myPassword
grant_type: password
scope: openid profile offline_access
我只收到范围,token_type、access_token、expires_in 和 id_token,没有 refresh_token。
我错过了什么?
options.AllowPasswordFlow();
刷新令牌不能与密码流程一起使用,因为在此流程中用户永远不会被重定向到 Auth Server 登录,so can’t directly authorize the application:
If the application uses the username-password OAuth authentication flow, no refresh token is issued, as the user cannot authorize the application in this flow. If the access token expires, the application using username-password OAuth flow must re-authenticate the user.
OAuth2 规范绝对允许使用密码返回刷新令牌,因此,OpenIddict 完全支持。
对于 OpenIddict 返回的刷新令牌,您必须在调用 SignIn
时授予特殊的 offline_access
范围。例如:
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