从IdentityServer4迁移到OpenIddict后刷新令牌遇scope无效错误
从IdentityServer4迁移到OpenIddict后刷新令牌报错'invalid_grant'
问题详情
正从IdentityServer4迁移到OpenIddict,authorization_code授权流程获取令牌正常,但刷新令牌时触发invalid_grant错误,错误描述为The specified 'scope' is invalid. while refreshing token.。
刷新令牌请求载荷
grant_type: refresh_token scope: openid roles offline_access refresh_token: *[redacted] client_id: js
服务器配置
.AddServer(options => { options.DisableAccessTokenEncryption(); options.SetAuthorizationEndpointUris("/authorize") .SetTokenEndpointUris("/token") .SetLogoutEndpointUris("/logout") .SetUserinfoEndpointUris("/userinfo"); options.AllowAuthorizationCodeFlow() .AllowRefreshTokenFlow(); options.RegisterScopes(Scopes.Profile, Scopes.Roles, Scopes.OfflineAccess, Scopes.OpenId, Scopes.Email, "api1"); options.RegisterClaims(Claims.Role, Claims.Profile, Claims.Name, Claims.Subject, "user_type"); options.AddEncryptionKey(new SymmetricSecurityKey( Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY="))); // Register the signing credentials. options.AddDevelopmentSigningCertificate(); options.UseAspNetCore() .EnableAuthorizationEndpointPassthrough() .EnableLogoutEndpointPassthrough() .EnableTokenEndpointPassthrough() .EnableUserinfoEndpointPassthrough(); options.SetAccessTokenLifetime(TimeSpan.FromSeconds(50)); }) .AddValidation(options => { options.UseLocalServer(); options.UseAspNetCore(); });
应用客户端配置
await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "js", ConsentType = ConsentTypes.External, DisplayName = "angular client PKCE", DisplayNames = { [CultureInfo.GetCultureInfo("th-TH")] = "Application client" }, PostLogoutRedirectUris = { new Uri("https://localhost.domain.com") }, RedirectUris = { new Uri("https://localhost.domain.com/callback") }, Permissions = { Permissions.Endpoints.Authorization, Permissions.Endpoints.Logout, Permissions.Endpoints.Token, Permissions.Endpoints.Revocation, Permissions.GrantTypes.AuthorizationCode, Permissions.GrantTypes.RefreshToken, Permissions.ResponseTypes.Code, Permissions.Scopes.Profile, Permissions.Scopes.Roles, Permissions.Prefixes.Scope + "api1" }, Requirements = { Requirements.Features.ProofKeyForCodeExchange } });
相关OpenID配置
"scopes_supported": [ "openid", "offline_access", "profile", "roles", "email", "api1" ],
疑问:已禁用AccessToken加密(因为Angular客户端需要读取sub获取用户ID),这是否是问题原因?未发现缺失的scope。
问题原因及解决方法
- 客户端权限缺失:客户端配置的
Permissions集合中未添加Permissions.Scopes.OfflineAccess权限,而刷新令牌请求包含了offline_accessscope,OpenIddict会校验客户端是否被允许请求该scope,这是触发错误的核心原因。需要在客户端权限中添加该条目。 - 刷新令牌scope范围限制:刷新令牌时,请求的scope不能超出初始授权码流程中获取的scope集合,同时所有请求的scope必须都被客户端授权。需确认初始授权时是否包含
openid、roles、offline_access这些scope。 - AccessToken加密的影响:禁用AccessToken加密不是导致该错误的原因,该配置仅用于让客户端直接读取JWT中的声明,与刷新令牌的scope校验无关。
修改后的客户端权限配置应补充:
Permissions = { // 保留原有所有权限... Permissions.Scopes.OfflineAccess, // 保留原有所有权限... }
内容的提问来源于stack exchange,提问作者Elger Mensonides
相关产品推荐
相关产品推荐

