问题描述
自从从 OpenIdDict 2.x 迁移到 3.X,我们不能再使用 refreshtoken。 我们的代码基于 dotnet core 3.1
用户/密码的处理工作正常,用户收到他的令牌(访问、id 和刷新)
但是一旦我们想要发送刷新令牌,从用户那里获取主体的过程就会返回一个空值。
var 信息 = 等待 HttpContext.AuthenticateAsync(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme); var user = await _userManager.GetUserAsync(info.Principal);
错误信息
System.ArgumentNullException:值不能为空。 (范围 '校长')
这是我们用来引导 Openiddict 的代码
startup.cs
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<DataContext>();
})
.AddServer(options =>
{
options.SetTokenEndpointUris("/connect/token")
.AllowPasswordFlow()
.AllowRefreshTokenFlow();
options.SetAccesstokenLifetime(TimeSpan.FromDays(1));
options.SetRefreshTokenLifetime(TimeSpan.FromDays(1));
options.AcceptAnonymousClients();
options.AddDevelopmentEncryptionCertificate();
options.AddDevelopmentSigningCertificate();
options.RequireProofKeyForCodeExchange();
options.UseAspNetCore()
.EnabletokenEndpointPassthrough();
})
.AddValidation(options =>
{
options.UseLocalServer();
options.UseAspNetCore();
});
授权控制器.cs
[HttpPost("~/connect/token")]
public async Task<IActionResult> Login()
{
var request = HttpContext.GetopenIddictServerRequest() ??
throw new InvalidOperationException(
"The OpenID Connect request cannot be retrieved.");
if (request.IsPasswordGrantType())
{
return await CheckPasswordGrantType(request);
}
if (request.IsRefreshTokenGrantType())
{
return await CheckRefreshTokenGrantType();
}
throw new NotImplementedException("The specified grant type is not implemented.");
}
private async Task<IActionResult> CheckRefreshTokenGrantType()
{
var info = await HttpContext.AuthenticateAsync(
OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
var user = await _userManager.GetUserAsync(info.Principal);
if (user == null)
{
var properties = new AuthenticationProperties(new Dictionary<string,string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
OpenIddictConstants.Errors.InvalidGrant,[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
"The refresh token is no longer valid."
});
return Forbid(properties,OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
}
if (user.EmailConfirmed == false)
{
var properties = new AuthenticationProperties(new Dictionary<string,[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
"Email address not confirmed."
});
return Forbid(properties,OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
}
if (!await _signInManager.CanSignInAsync(user))
{
var properties = new AuthenticationProperties(new Dictionary<string,[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
"The user is no longer allowed to sign in."
});
return Forbid(properties,OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
}
foreach (var claim in info.Principal.Claims)
{
claim.SetDestinations(GetDestinations(claim,info.Principal));
}
return SignIn(info.Principal,OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
private async Task<IActionResult> CheckPasswordGrantType(OpenIddictRequest request)
{
var user = await _userManager.FindByNameAsync(request.Username);
if (user == null)
{
var properties = new AuthenticationProperties(new Dictionary<string,string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
OpenIddictConstants.Errors.InvalidGrant,[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
"The username/password couple is invalid."
});
return Forbid(properties,string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
OpenIddictConstants.Errors.AccessDenied,[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
"Email address not confirmed."
});
return Forbid(properties,OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
}
var result =
await _signInManager.CheckPasswordSignInAsync(user,request.Password,true);
if (!result.Succeeded)
{
if (result.IsLockedOut)
{
var properties =
new AuthenticationProperties(new Dictionary<string,string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
OpenIddictConstants.Errors.InvalidRequest,[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
"Account locked : too many attempts."
});
return Forbid(properties,OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
}
else
{
var properties =
new AuthenticationProperties(new Dictionary<string,string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] =
OpenIddictConstants.Errors.InvalidGrant,[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] =
"The username/password couple is invalid."
});
return Forbid(properties,OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
}
}
var principal = await _signInManager.createuserPrincipalAsync(user);
principal.SetScopes(new[]
{
OpenIddictConstants.Scopes.OpenId,OpenIddictConstants.Scopes.Email,OpenIddictConstants.Scopes.Profile,OpenIddictConstants.Scopes.Roles,OpenIddictConstants.Scopes.OfflineAccess
}.Intersect(request.GetScopes()));
foreach (var claim in principal.Claims)
{
claim.SetDestinations(GetDestinations(claim,principal));
}
return SignIn(principal,OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
private IEnumerable<string> GetDestinations(Claim claim,ClaimsPrincipal principal)
{
switch (claim.Type)
{
case OpenIddictConstants.Claims.Name:
yield return OpenIddictConstants.Destinations.Accesstoken;
if (principal.HasScope(OpenIddictConstants.Scopes.Profile))
yield return OpenIddictConstants.Destinations.IdentityToken;
yield break;
case OpenIddictConstants.Claims.Email:
yield return OpenIddictConstants.Destinations.Accesstoken;
if (principal.HasScope(OpenIddictConstants.Scopes.Email))
yield return OpenIddictConstants.Destinations.IdentityToken;
yield break;
case OpenIddictConstants.Claims.Role:
yield return OpenIddictConstants.Destinations.Accesstoken;
if (principal.HasScope(OpenIddictConstants.Scopes.Roles))
yield return OpenIddictConstants.Destinations.IdentityToken;
yield break;
case "AspNet.Identity.SecurityStamp": yield break;
default:
yield return OpenIddictConstants.Destinations.Accesstoken;
yield break;
}
}
大部分代码来自 OpenIddict 的示例。
我真的不明白这是怎么回事
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)