我可能会说这一切都错了,但我一直在关注本文中的示例设置:Creating your own OpenID Connect server with ASOS,但是,它没有解释如何实现两个因素,因为这不是这个的主要目的文章。
本文中唯一提到的两个派系是在令牌端点,其中有一个双因素身份验证检查,如果启用了两个因子,它会拒绝令牌请求。所以我在我的客户端应用程序中添加了一个检查,检查特定的拒绝条件,然后重定向到要求两个因子代码的页面。该页面首先调用授权端点,该端点将代码发送到存档的用户电话。然后,一旦用户输入了代码,它就会再次使用该代码调用授权端点,并且处理授权端点的方法会验证代码并在成功时返回SignInResult。但是,我在返回SignInResult的SignIn(原则,属性,架构)方法中遇到500错误。
首先,我想知道我是否正确行事,其次,如果我做得正确,我做错了什么?请在下面找到我的相关代码:
AuthorizationProvider:
public override async Task HandleTokenRequest(HandleTokenRequestContext context) {
var _dbContext = context.HttpContext.RequestServices.GetRequiredService<DbContext>();
if(context.Request.IsPasswordGrantType()) {
var u = await _dbContext.Users.Include(m => m.Organization).SingleOrDefaultAsync(x => x.Email.ToLowerInvariant() == context.Request.Username.ToLowerInvariant());
if(u == null || !PasswordHelper.VerifyPassword(context.Request.Password, u.Password)) {
context.Reject(
error: OpenIdConnectConstants.Errors.AccessDenied,
description: "The email or password is incorrect");
return;
} else if(u.Organization == null) {
context.Reject(
error: OpenIdConnectConstants.Errors.InvalidGrant,
description: "Your user account is not associated with an organization.");
return;
}
// // Reject the token request if two-factor authentication has been enabled by the user.
if(u.TwoFactorEnabled) {
context.Reject(
error: OpenIdConnectConstants.Errors.InvalidGrant,
description: "Two-factor authentication is required for this account.");
return;
}
var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);
List<Claim> claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.NameIdentifier, u.Id.ToString()));
claims.Add(new Claim(ClaimTypes.Name, context.Request.Username));
claims.Add(new Claim(ClaimTypes.Role, u.RoleString));
claims.Add(new Claim("user_id", u.Id.ToString()));
claims.Add(new Claim("org_id", u.Organization.Id.ToString()));
foreach(var claim in claims) {
claim.SetDestinations(new List<string> { OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken });
}
identity.AddClaims(claims);
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
context.Options.AuthenticationScheme);
// Set the list of scopes granted to the client application.
ticket.SetScopes(
/* openid: */ OpenIdConnectConstants.Scopes.OpenId,
/* email: */ OpenIdConnectConstants.Scopes.Email,
/* profile: */ OpenIdConnectConstants.Scopes.Profile,
/* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess);
context.Validate(ticket);
}
}
授权方法:
[HttpPost]
[Route("authorize")]
public async Task<IActionResult> Authorize() {
var request = HttpContext.GetOpenIdConnectRequest();
if(request.Code == null) {
var u = await _dbContext.Users.SingleOrDefaultAsync(x => x.Email.ToLowerInvariant() == request.Username.ToLowerInvariant());
if(u == null || !PasswordHelper.VerifyPassword(request.Password, u.Password)) {
return Forbid(OpenIdConnectServerDefaults.AuthenticationScheme);
}
var response = await _twoFactorProvider.SendCode(CodeMethods.sms, u.AuthyId);
return Ok(new { Id = u.AuthyId, Response = response });
} else {
var response = await _twoFactorProvider.VerifyCode(request.Code, int.Parse(request.Username));
if(response.Token != "is valid") {
return Forbid(OpenIdConnectServerDefaults.AuthenticationScheme);
}
var u = await _dbContext.Users.Include(m => m.Organization).SingleOrDefaultAsync(x => x.AuthyId == int.Parse(request.Username));
var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
List<Claim> claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.NameIdentifier, u.Id.ToString()));
claims.Add(new Claim(ClaimTypes.Name, u.Email));
claims.Add(new Claim(ClaimTypes.Role, u.RoleString));
claims.Add(new Claim("user_id", u.Id.ToString()));
claims.Add(new Claim("org_id", u.Organization.Id.ToString()));
foreach(var claim in claims) {
claim.SetDestinations(new List<string> { OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken });
}
identity.AddClaims(claims);
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
OpenIdConnectServerDefaults.AuthenticationScheme);
// Set the list of scopes granted to the client application.
ticket.SetScopes(
/* openid: */ OpenIdConnectConstants.Scopes.OpenId,
/* email: */ OpenIdConnectConstants.Scopes.Email,
/* profile: */ OpenIdConnectConstants.Scopes.Profile,
/* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess);
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
}
客户端方法:
login(email, password) {
var deferred = q.defer();
var payload = {
'grant_type': 'password',
'username': email,
'password': password,
'scope': 'openid offline_access'
};
var url = this.authContextConfiguration.baseUrl + 'connect/token';
$.ajax({
url: url,
type: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: payload,
success: function (data) {
// store the access token / everything else //
deferred.resolve();
},
error: function (req) {
var error = {
message: req.responseJSON.error_description || 'There was an error when signing in.'
};
deferred.reject(error);
}
});
return deferred.promise;
}
twoFactorLogin(email, password) {
var deferred = q.defer();
var payload = {
'username': email,
'password': password
}
var url = this.authContextConfiguration.baseUrl + 'connect/authorize';
$.ajax({
url: url,
type: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: payload,
success: function (data) {
deferred.resolve(data);
},
error: function (req) {
var error = {
message: req.responseJSON.error_description || 'There was an error generating your two factor code.'
};
deferred.reject(error);
}
});
return deferred.promise;
}
verifyTwoFactorCode(id, code, remember) {
var deferred = q.defer();
var payload = {
'username': id,
'code': code,
'rememberMe': remember
}
var url = this.authContextConfiguration.baseUrl + 'connect/authorize';
$.ajax({
url: url,
type: 'POST',
contentType: 'application/x-www-form-urlencoded',
data: payload,
success: function (data) {
deferred.resolve(data);
},
error: function (req) {
var error = {
message: req.responseJSON.error_description || 'There was an error verifying your two factor code.'
};
deferred.reject(error);
}
});
return deferred.promise;
}