Rename Unintuitive Function Names in Authentication Flow (#9706)

Resolves #9623

## Description

This PR renames the following functions to better reflect their purpose.

- Backend:
  - Verify → GetAuthTokensFromLoginToken
  - Challenge → GetLoginTokenFromCredentials

- Frontend:
  - challenge → getLoginTokenFromCredentials
  - verify → getAuthTokensFromLoginToken

## Testing
_Sign in works as expected:_


https://github.com/user-attachments/assets/7e8f73c7-2c7d-4cd2-9965-5ad9f5334cd3

_Sign up works as expected:_
  

https://github.com/user-attachments/assets/d1794ee4-8b59-4934-84df-d819eabd5224

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Samyak Piya
2025-01-24 13:19:14 -05:00
committed by GitHub
parent 570b2e3530
commit 55be726105
19 changed files with 300 additions and 259 deletions

View File

@ -44,13 +44,13 @@ import { OriginHeader } from 'src/engine/decorators/auth/origin-header.decorator
import { UserAuthGuard } from 'src/engine/guards/user-auth.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { ChallengeInput } from './dto/challenge.input';
import { GetAuthTokensFromLoginTokenInput } from './dto/get-auth-tokens-from-login-token.input';
import { GetLoginTokenFromCredentialsInput } from './dto/get-login-token-from-credentials.input';
import { LoginToken } from './dto/login-token.entity';
import { SignUpInput } from './dto/sign-up.input';
import { ApiKeyToken, AuthTokens } from './dto/token.entity';
import { UserExistsOutput } from './dto/user-exists.entity';
import { CheckUserExistsInput } from './dto/user-exists.input';
import { VerifyInput } from './dto/verify.input';
import { WorkspaceInviteHashValid } from './dto/workspace-invite-hash-valid.entity';
import { WorkspaceInviteHashValidInput } from './dto/workspace-invite-hash.input';
import { AuthService } from './services/auth.service';
@ -103,8 +103,9 @@ export class AuthResolver {
@UseGuards(CaptchaGuard)
@Mutation(() => LoginToken)
async challenge(
@Args() challengeInput: ChallengeInput,
async getLoginTokenFromCredentials(
@Args()
getLoginTokenFromCredentialsInput: GetLoginTokenFromCredentialsInput,
@OriginHeader() origin: string,
): Promise<LoginToken> {
const workspace =
@ -119,7 +120,12 @@ export class AuthResolver {
AuthExceptionCode.WORKSPACE_NOT_FOUND,
),
);
const user = await this.authService.challenge(challengeInput, workspace);
const user = await this.authService.getLoginTokenFromCredentials(
getLoginTokenFromCredentialsInput,
workspace,
);
const loginToken = await this.loginTokenService.generateLoginToken(
user.email,
workspace.id,
@ -265,8 +271,8 @@ export class AuthResolver {
}
@Mutation(() => AuthTokens)
async verify(
@Args() verifyInput: VerifyInput,
async getAuthTokensFromLoginToken(
@Args() getAuthTokensFromLoginTokenInput: GetAuthTokensFromLoginTokenInput,
@OriginHeader() origin: string,
): Promise<AuthTokens> {
const workspace =
@ -277,7 +283,9 @@ export class AuthResolver {
workspaceValidator.assertIsDefinedOrThrow(workspace);
const { sub: email, workspaceId } =
await this.loginTokenService.verifyLoginToken(verifyInput.loginToken);
await this.loginTokenService.verifyLoginToken(
getAuthTokensFromLoginTokenInput.loginToken,
);
if (workspaceId !== workspace.id) {
throw new AuthException(

View File

@ -3,7 +3,7 @@ import { ArgsType, Field } from '@nestjs/graphql';
import { IsNotEmpty, IsString } from 'class-validator';
@ArgsType()
export class VerifyInput {
export class GetAuthTokensFromLoginTokenInput {
@Field(() => String)
@IsNotEmpty()
@IsString()

View File

@ -3,7 +3,7 @@ import { ArgsType, Field } from '@nestjs/graphql';
import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
@ArgsType()
export class ChallengeInput {
export class GetLoginTokenFromCredentialsInput {
@Field(() => String)
@IsNotEmpty()
@IsEmail()

View File

@ -6,9 +6,15 @@ import bcrypt from 'bcrypt';
import { Repository } from 'typeorm';
import { AppToken } from 'src/engine/core-modules/app-token/app-token.entity';
import {
AuthException,
AuthExceptionCode,
} from 'src/engine/core-modules/auth/auth.exception';
import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service';
import { SocialSsoService } from 'src/engine/core-modules/auth/services/social-sso.service';
import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service';
import { RefreshTokenService } from 'src/engine/core-modules/auth/token/services/refresh-token.service';
import { ExistingUserOrNewUser } from 'src/engine/core-modules/auth/types/signInUp.type';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
import { EmailService } from 'src/engine/core-modules/email/email.service';
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
@ -16,13 +22,7 @@ import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/use
import { UserService } from 'src/engine/core-modules/user/services/user.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
import { SocialSsoService } from 'src/engine/core-modules/auth/services/social-sso.service';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { ExistingUserOrNewUser } from 'src/engine/core-modules/auth/types/signInUp.type';
import {
AuthException,
AuthExceptionCode,
} from 'src/engine/core-modules/auth/auth.exception';
import { AuthService } from './auth.service';
@ -165,7 +165,7 @@ describe('AuthService', () => {
userWorkspaceServiceCheckUserWorkspaceExistsMock.mockReturnValueOnce({});
const response = await service.challenge(
const response = await service.getLoginTokenFromCredentials(
{
email: 'email',
password: 'password',
@ -201,7 +201,7 @@ describe('AuthService', () => {
workspaceInvitationValidatePersonalInvitationMock.mockReturnValueOnce({});
userWorkspaceAddUserToWorkspaceMock.mockReturnValueOnce({});
const response = await service.challenge(
const response = await service.getLoginTokenFromCredentials(
{
email: 'email',
password: 'password',

View File

@ -26,7 +26,7 @@ import {
} from 'src/engine/core-modules/auth/auth.util';
import { AuthorizeApp } from 'src/engine/core-modules/auth/dto/authorize-app.entity';
import { AuthorizeAppInput } from 'src/engine/core-modules/auth/dto/authorize-app.input';
import { ChallengeInput } from 'src/engine/core-modules/auth/dto/challenge.input';
import { GetLoginTokenFromCredentialsInput } from 'src/engine/core-modules/auth/dto/get-login-token-from-credentials.input';
import { AuthTokens } from 'src/engine/core-modules/auth/dto/token.entity';
import { UpdatePassword } from 'src/engine/core-modules/auth/dto/update-password.entity';
import {
@ -35,26 +35,26 @@ import {
} from 'src/engine/core-modules/auth/dto/user-exists.entity';
import { WorkspaceInviteHashValid } from 'src/engine/core-modules/auth/dto/workspace-invite-hash-valid.entity';
import { SignInUpService } from 'src/engine/core-modules/auth/services/sign-in-up.service';
import { SocialSsoService } from 'src/engine/core-modules/auth/services/social-sso.service';
import { AccessTokenService } from 'src/engine/core-modules/auth/token/services/access-token.service';
import { RefreshTokenService } from 'src/engine/core-modules/auth/token/services/refresh-token.service';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
import { EmailService } from 'src/engine/core-modules/email/email.service';
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { userValidator } from 'src/engine/core-modules/user/user.validate';
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { SocialSsoService } from 'src/engine/core-modules/auth/services/social-sso.service';
import { UserService } from 'src/engine/core-modules/user/services/user.service';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
import {
AuthProviderWithPasswordType,
ExistingUserOrNewUser,
SignInUpBaseParams,
SignInUpNewUserPayload,
} from 'src/engine/core-modules/auth/types/signInUp.type';
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
import { EmailService } from 'src/engine/core-modules/email/email.service';
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { UserService } from 'src/engine/core-modules/user/services/user.service';
import { User } from 'src/engine/core-modules/user/user.entity';
import { userValidator } from 'src/engine/core-modules/user/user.validate';
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
@Injectable()
// eslint-disable-next-line @nx/workspace-inject-workspace-repository
@ -113,7 +113,10 @@ export class AuthService {
);
}
async challenge(challengeInput: ChallengeInput, targetWorkspace: Workspace) {
async getLoginTokenFromCredentials(
input: GetLoginTokenFromCredentialsInput,
targetWorkspace: Workspace,
) {
if (!targetWorkspace.isPasswordAuthEnabled) {
throw new AuthException(
'Email/Password auth is not enabled for this workspace',
@ -123,7 +126,7 @@ export class AuthService {
const user = await this.userRepository.findOne({
where: {
email: challengeInput.email,
email: input.email,
},
relations: ['workspaces'],
});
@ -144,10 +147,7 @@ export class AuthService {
);
}
const isValid = await compareHash(
challengeInput.password,
user.passwordHash,
);
const isValid = await compareHash(input.password, user.passwordHash);
if (!isValid) {
throw new AuthException(