feat(auth): replace TOTP with phone-first login

This commit is contained in:
2026-07-28 17:39:29 +08:00
parent e7d350ec3d
commit c7f9a4e3c9
43 changed files with 18386 additions and 882 deletions

View File

@@ -52,10 +52,6 @@ public enum AuthenticationStatus
{
[JsonStringEnumMemberName("authenticated")]
Authenticated,
[JsonStringEnumMemberName("mfa_required")]
MfaRequired,
[JsonStringEnumMemberName("mfa_enrollment_required")]
MfaEnrollmentRequired,
[JsonStringEnumMemberName("password_change_required")]
PasswordChangeRequired
}
@@ -97,24 +93,12 @@ public sealed record RefreshSessionRequest(
public sealed record LogoutSessionRequest(
string RefreshToken);
public sealed record MfaChallengeRequest(
string ChallengeToken,
string? Code,
string? IpAddress,
string? UserAgent);
public sealed record PasswordChangeChallengeRequest(
string ChallengeToken,
string NewPassword,
string? IpAddress,
string? UserAgent);
public sealed record MfaSetupResult(string SharedKey, string AuthenticatorUri);
public sealed record MfaConfirmResult(
AuthenticationResult Authentication,
IReadOnlyList<string> RecoveryCodes);
public sealed record SmsSendResult(
Guid VerificationId,
DateTimeOffset ExpiresAt);

View File

@@ -28,18 +28,6 @@ public interface IAuthService
Task LogoutAllAsync(Guid userId, CancellationToken cancellationToken = default);
Task<MfaSetupResult> SetupTotpAsync(
MfaChallengeRequest request,
CancellationToken cancellationToken = default);
Task<MfaConfirmResult> ConfirmTotpAsync(
MfaChallengeRequest request,
CancellationToken cancellationToken = default);
Task<AuthenticationResult> VerifyTotpAsync(
MfaChallengeRequest request,
CancellationToken cancellationToken = default);
Task<AuthenticationResult> ChangeRequiredPasswordAsync(
PasswordChangeChallengeRequest request,
CancellationToken cancellationToken = default);

View File

@@ -38,12 +38,11 @@ public sealed record AuthSessionIssueRequest(
AuthRealm Realm,
Guid? TenantId,
string Provider,
bool MfaSatisfied,
string? IpAddress,
string? UserAgent,
Guid? TokenFamilyId = null,
Guid? ParentSessionId = null);
public sealed record AuthSessionValidationResult(Guid UserId, AuthRealm Realm, Guid? TenantId, bool MfaSatisfied);
public sealed record AuthSessionValidationResult(Guid UserId, AuthRealm Realm, Guid? TenantId);
public readonly record struct RefreshTokenLocator(AuthRealm Realm, Guid? TenantId, Guid SessionId);

View File

@@ -10,6 +10,5 @@ public interface ITokenService
string? phone,
string? email,
AuthRealm realm,
Guid? tenantId,
bool mfaSatisfied);
Guid? tenantId);
}

View File

@@ -8,7 +8,6 @@ public static class TikuClaimTypes
public const string TenantId = "tid";
public const string SessionId = "sid";
public const string Realm = "scope";
public const string Mfa = "amr";
public const string Phone = ClaimTypes.MobilePhone;
public const string Email = ClaimTypes.Email;
}

View File

@@ -6,7 +6,6 @@ public static class TikuPolicies
public const string CurrentTenantMember = "current_tenant_member";
public const string TenantBackofficeBootstrap = "tenant_backoffice_bootstrap";
public const string PlatformBackofficeBootstrap = "platform_backoffice_bootstrap";
public const string Mfa = "mfa";
public const string TenantContentManageAllScope = "tenant:content:manage:all_scope";
public const string TenantCommerceOperateAllScope = "tenant:commerce:operate:all_scope";