Browse Source

Merge pull request #25649 from abpframework/auto-merge/rel-10-4/4664

Merge branch rel-10.5 with rel-10.4
pull/25650/head
Volosoft Agent 3 months ago
committed by GitHub
parent
commit
ef1dc16840
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 129
      modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs
  2. 106
      modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.TokenExchange.cs

129
modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs

@ -57,24 +57,30 @@ public partial class TokenController
if (await externalLoginProvider.TryAuthenticateAsync(request.Username, request.Password)) if (await externalLoginProvider.TryAuthenticateAsync(request.Username, request.Password))
{ {
user = await UserManager.FindByNameAsync(request.Username); user = await UserManager.FindSharedUserByNameAsync(request.Username);
if (user == null) if (user == null)
{ {
user = await externalLoginProvider.CreateUserAsync(request.Username, externalLoginProviderInfo.Name); user = await externalLoginProvider.CreateUserAsync(request.Username, externalLoginProviderInfo.Name);
} }
else else
{ {
await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name); using (CurrentTenant.Change(user.TenantId))
{
await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name);
}
} }
return await SetSuccessResultAsync(request, user); using (CurrentTenant.Change(user.TenantId))
{
return await SetSuccessResultAsync(request, user);
}
} }
} }
} }
await IdentityOptions.SetAsync(); await IdentityOptions.SetAsync();
user = await UserManager.FindByNameAsync(request.Username); user = await UserManager.FindSharedUserByNameAsync(request.Username);
if (user == null) if (user == null)
{ {
Logger.LogInformation("No user found matching username: {username}", request.Username); Logger.LogInformation("No user found matching username: {username}", request.Username);
@ -96,77 +102,82 @@ public partial class TokenController
return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
} }
var result = await SignInManager.CheckPasswordSignInAsync(user, request.Password, true); using (CurrentTenant.Change(user.TenantId))
if (!result.Succeeded)
{ {
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext await IdentityOptions.SetAsync();
var result = await SignInManager.CheckPasswordSignInAsync(user, request.Password, true);
if (!result.Succeeded)
{ {
Identity = OpenIddictSecurityLogIdentityConsts.OpenIddict, await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
Action = result.ToIdentitySecurityLogAction(), {
UserName = request.Username, Identity = OpenIddictSecurityLogIdentityConsts.OpenIddict,
ClientId = request.ClientId Action = result.ToIdentitySecurityLogAction(),
}); UserName = request.Username,
ClientId = request.ClientId
});
var errorCode = OpenIddictConstants.Errors.InvalidGrant; var errorCode = OpenIddictConstants.Errors.InvalidGrant;
string errorDescription; string errorDescription;
if (result.IsLockedOut) if (result.IsLockedOut)
{
Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", request.Username);
errorCode = AbpOpenIddictErrors.AccountLocked;
errorDescription = "The user account has been locked out due to invalid login attempts. Please wait a while and try again.";
}
else if (result.IsNotAllowed)
{
if (!await UserManager.CheckPasswordAsync(user, request.Password))
{ {
Logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", request.Username); Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", request.Username);
errorDescription = "Invalid username or password!"; errorCode = AbpOpenIddictErrors.AccountLocked;
errorDescription = "The user account has been locked out due to invalid login attempts. Please wait a while and try again.";
} }
else else if (result.IsNotAllowed)
{ {
Logger.LogInformation("Authentication failed for username: {username}, reason: not allowed", request.Username); if (!await UserManager.CheckPasswordAsync(user, request.Password))
if (user.ShouldChangePasswordOnNextLogin)
{ {
return await HandleShouldChangePasswordOnNextLoginAsync(request, user, request.Password); Logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", request.Username);
errorDescription = "Invalid username or password!";
} }
else
if (await UserManager.ShouldPeriodicallyChangePasswordAsync(user))
{ {
return await HandlePeriodicallyChangePasswordAsync(request, user, request.Password); Logger.LogInformation("Authentication failed for username: {username}, reason: not allowed", request.Username);
}
if (user.IsActive) if (user.ShouldChangePasswordOnNextLogin)
{ {
return await HandleConfirmUserAsync(request, user); return await HandleShouldChangePasswordOnNextLoginAsync(request, user, request.Password);
} }
if (await UserManager.ShouldPeriodicallyChangePasswordAsync(user))
{
return await HandlePeriodicallyChangePasswordAsync(request, user, request.Password);
}
errorCode = AbpOpenIddictErrors.AccountInactive; if (user.IsActive)
errorDescription = "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number."; {
return await HandleConfirmUserAsync(request, user);
}
errorCode = AbpOpenIddictErrors.AccountInactive;
errorDescription = "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.";
}
} }
} else
else {
{ Logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", request.Username);
Logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", request.Username); errorDescription = "Invalid username or password!";
errorDescription = "Invalid username or password!"; }
var properties = new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = errorCode,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = errorDescription
});
return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
} }
var properties = new AuthenticationProperties(new Dictionary<string, string> if (await IsTfaEnabledAsync(user))
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = errorCode, return await HandleTwoFactorLoginAsync(request, user);
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = errorDescription }
});
return Forbid(properties, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
if (await IsTfaEnabledAsync(user)) return await SetSuccessResultAsync(request, user);
{
return await HandleTwoFactorLoginAsync(request, user);
} }
return await SetSuccessResultAsync(request, user);
} }
} }
} }
@ -178,13 +189,13 @@ public partial class TokenController
return; return;
} }
var userByUsername = await UserManager.FindByNameAsync(request.Username); var userByUsername = await UserManager.FindSharedUserByNameAsync(request.Username);
if (userByUsername != null) if (userByUsername != null)
{ {
return; return;
} }
var userByEmail = await UserManager.FindByEmailAsync(request.Username); var userByEmail = await UserManager.FindSharedUserByEmailAsync(request.Username);
if (userByEmail == null) if (userByEmail == null)
{ {
return; return;

106
modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.TokenExchange.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal;
using System.Text.Json.Nodes; using System.Text.Json.Nodes;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
@ -27,66 +28,69 @@ public partial class TokenController
// If available, retrieve the claims principal stored in the actor token. // If available, retrieve the claims principal stored in the actor token.
var actor = result.Properties?.GetParameter<ClaimsPrincipal>(OpenIddictServerAspNetCoreConstants.Properties.ActorTokenPrincipal); var actor = result.Properties?.GetParameter<ClaimsPrincipal>(OpenIddictServerAspNetCoreConstants.Properties.ActorTokenPrincipal);
// Retrieve the user profile corresponding to the subject token. using (CurrentTenant.Change(result.Principal!.FindTenantId()))
var user = await UserManager.FindByIdAsync(result.Principal!.GetClaim(OpenIddictConstants.Claims.Subject)!);
if (user is null)
{ {
return Forbid( // Retrieve the user profile corresponding to the subject token.
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, var user = await UserManager.FindByIdAsync(result.Principal!.GetClaim(OpenIddictConstants.Claims.Subject)!);
properties: new AuthenticationProperties(new Dictionary<string, string> if (user is null)
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant, return Forbid(
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid." authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
})); properties: new AuthenticationProperties(new Dictionary<string, string>
} {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The token is no longer valid."
}));
}
// Ensure the user is still allowed to sign in. // Ensure the user is still allowed to sign in.
if (!await PreSignInCheckAsync(user)) if (!await PreSignInCheckAsync(user))
{ {
return Forbid( return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string?> properties: new AuthenticationProperties(new Dictionary<string, string?>
{ {
[OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant, [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in." [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is no longer allowed to sign in."
})); }));
} }
// Note: whether the identity represents a delegated or impersonated access (or any other // Note: whether the identity represents a delegated or impersonated access (or any other
// model) is entirely up to the implementer: to support all scenarios, OpenIddict doesn't // model) is entirely up to the implementer: to support all scenarios, OpenIddict doesn't
// enforce any specific constraint on the identity used for the sign-in operation and only // enforce any specific constraint on the identity used for the sign-in operation and only
// requires that the standard "act" and "may_act" claims be valid JSON objects if present. // requires that the standard "act" and "may_act" claims be valid JSON objects if present.
// Clear the dynamic claims cache. // Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId); await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
// Create a new ClaimsPrincipal containing the claims that // Create a new ClaimsPrincipal containing the claims that
// will be used to create an id_token, a token or a code. // will be used to create an id_token, a token or a code.
var principal = await SignInManager.CreateUserPrincipalAsync(user); var principal = await SignInManager.CreateUserPrincipalAsync(user);
// Note: IdentityModel doesn't support serializing ClaimsIdentity.Actor to the // Note: IdentityModel doesn't support serializing ClaimsIdentity.Actor to the
// standard "act" claim yet, which requires adding the "act" claim manually. // standard "act" claim yet, which requires adding the "act" claim manually.
// //
// For more information, see // For more information, see
// https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/3219. // https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/3219.
if (!string.IsNullOrEmpty(actor?.GetClaim(OpenIddictConstants.Claims.Subject)) && if (!string.IsNullOrEmpty(actor?.GetClaim(OpenIddictConstants.Claims.Subject)) &&
!string.Equals(principal.GetClaim(OpenIddictConstants.Claims.Subject), actor.GetClaim(OpenIddictConstants.Claims.Subject), StringComparison.Ordinal)) !string.Equals(principal.GetClaim(OpenIddictConstants.Claims.Subject), actor.GetClaim(OpenIddictConstants.Claims.Subject), StringComparison.Ordinal))
{
principal.SetClaim(OpenIddictConstants.Claims.Actor, new JsonObject
{ {
[OpenIddictConstants.Claims.Subject] = actor.GetClaim(OpenIddictConstants.Claims.Subject) principal.SetClaim(OpenIddictConstants.Claims.Actor, new JsonObject
}); {
} [OpenIddictConstants.Claims.Subject] = actor.GetClaim(OpenIddictConstants.Claims.Subject)
});
}
// Note: in this sample, the granted scopes match the requested scope // Note: in this sample, the granted scopes match the requested scope
// but you may want to allow the user to uncheck specific scopes. // but you may want to allow the user to uncheck specific scopes.
// For that, simply restrict the list of scopes before calling SetScopes. // For that, simply restrict the list of scopes before calling SetScopes.
principal.SetScopes(request.GetScopes()); principal.SetScopes(request.GetScopes());
principal.SetResources(await GetResourcesAsync(request.GetScopes())); principal.SetResources(await GetResourcesAsync(request.GetScopes()));
await OpenIddictClaimsPrincipalManager.HandleAsync(request, principal); await OpenIddictClaimsPrincipalManager.HandleAsync(request, principal);
// Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens. // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
} }
} }

Loading…
Cancel
Save