Skip to content

Commit

Permalink
chore: add option to skip 2FA
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex4386 committed Sep 4, 2022
1 parent 93dd017 commit ab5b416
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/common/meiling/v1/interfaces/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface PasswordResetBody {
export interface SigninTwoFactor {
type: SigninType.TWO_FACTOR_AUTH;
data?: SigninAuthenticationData;
skip2FA?: boolean;
}

interface SigninPasswordLess {
Expand Down
7 changes: 6 additions & 1 deletion src/common/meiling/v1/interfaces/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ExtendedAuthMethods, SigninType } from './query';
export interface MeilingSession {
user?: LoggedInUser[];
extendedAuthentication?: ExtendedAuthentication;
previouslyLoggedIn?: LoggedInUser[];
previouslyLoggedIn?: PreviouslyLoggedInUser[];
authenticationStatus?: SessionAuthenticationStatus;
passwordReset?: SessionPasswordReset;
registering?: SessionRegistering;
Expand All @@ -30,6 +30,11 @@ export interface LoggedInUser {
id: string;
}

export interface PreviouslyLoggedInUser {
id: string;
skip2FA?: boolean;
}

export interface SessionPasswordReset extends SessionChallengeBody {
method?: ExtendedAuthMethods;
passwordResetUser?: string;
Expand Down
26 changes: 25 additions & 1 deletion src/common/meiling/v1/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,29 @@ export async function setExtendedAuthenticationSessionMethodAndChallenge(
}
}

export async function canSkip2FA(req: FastifyRequest, user: UserModel | string): Promise<boolean> {
const session = await getSessionFromRequest(req);

if (session) {
if (session.previouslyLoggedIn === undefined) {
session.previouslyLoggedIn = [];
}

const userData = await Meiling.Identity.User.getBasicInfo(user);
if (userData === null || userData === undefined) {
return false;
}

const userId = userData.id;

const result = session.previouslyLoggedIn.find((n) => n.id === userId);

return result !== null && result?.skip2FA === true;
} else {
return false;
}
}

export async function getPreviouslyLoggedIn(req: FastifyRequest, user: UserModel | string): Promise<boolean> {
const session = await getSessionFromRequest(req);

Expand All @@ -467,7 +490,7 @@ export async function getPreviouslyLoggedIn(req: FastifyRequest, user: UserModel
}
}

export async function login(req: FastifyRequest, user: UserModel | string): Promise<void> {
export async function login(req: FastifyRequest, user: UserModel | string, skip2FA = false): Promise<void> {
const session = await getSessionFromRequest(req);

if (session) {
Expand All @@ -493,6 +516,7 @@ export async function login(req: FastifyRequest, user: UserModel | string): Prom
if (session.previouslyLoggedIn.map((user) => user.id === userData.id).indexOf(true) < 0) {
session.previouslyLoggedIn.push({
id: userData.id,
skip2FA,
});
}

Expand Down
39 changes: 25 additions & 14 deletions src/routes/v1/meiling/signin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export async function signinHandler(req: FastifyRequest, rep: FastifyReply): Pro
}

let userToLogin: UserModel;
let markToSkip2FA = false;

if (body.type === Meiling.V1.Interfaces.SigninType.USERNAME_CHECK) {
const username = body?.data?.username;

Expand Down Expand Up @@ -89,22 +91,27 @@ export async function signinHandler(req: FastifyRequest, rep: FastifyReply): Pro
}

const user = userToLogin;
const shouldSkip2FA = await Meiling.V1.Session.canSkip2FA(req, user);
if (user.useTwoFactor) {
const twoFactorMethods = await Meiling.V1.User.getAvailableExtendedAuthenticationMethods(user, body.type);
if (shouldSkip2FA) {
const twoFactorMethods = await Meiling.V1.User.getAvailableExtendedAuthenticationMethods(user, body.type);

if (twoFactorMethods.length > 0) {
// set the session for two factor authentication
if (twoFactorMethods.length > 0) {
// set the session for two factor authentication

await Meiling.V1.Session.setExtendedAuthenticationSession(req, {
id: user.id,
type: Meiling.V1.Interfaces.SigninType.TWO_FACTOR_AUTH,
});
await Meiling.V1.Session.setExtendedAuthenticationSession(req, {
id: user.id,
type: Meiling.V1.Interfaces.SigninType.TWO_FACTOR_AUTH,
});

throw new Meiling.V1.Error.MeilingError(
Meiling.V1.Error.ErrorType.TWO_FACTOR_AUTHENTICATION_REQUIRED,
'two factor authentication is required.',
);
return;
throw new Meiling.V1.Error.MeilingError(
Meiling.V1.Error.ErrorType.TWO_FACTOR_AUTHENTICATION_REQUIRED,
'two factor authentication is required.',
);
return;
}
} else {
markToSkip2FA = true;
}
}
} else if (
Expand Down Expand Up @@ -491,22 +498,26 @@ please request this endpoint without challengeResponse field to request challeng

if (authorizedUsers.length === 1) {
userToLogin = authorizedUsers[0];

if ((body as Meiling.V1.Interfaces.SigninTwoFactor).skip2FA === true) {
markToSkip2FA = true;
}
} else if (authorizedUsers.length > 1) {
throw new Meiling.V1.Error.MeilingError(
Meiling.V1.Error.ErrorType.MORE_THAN_ONE_USER_MATCHED,
'more than one user was matched, login using username instead.',
);
return;
} else {
throw new Meiling.V1.Error.MeilingError(Meiling.V1.Error.ErrorType.SIGNIN_FAILED, 'No matching users');
throw new Meiling.V1.Error.MeilingError(Meiling.V1.Error.ErrorType.SIGNIN_FAILED, 'invalid 2fa');
return;
}
} else {
throw new Meiling.V1.Error.MeilingError(Meiling.V1.Error.ErrorType.INVALID_SIGNIN_TYPE, 'invalid signin type.');
return;
}

await Meiling.V1.Session.login(req, userToLogin);
await Meiling.V1.Session.login(req, userToLogin, markToSkip2FA);
await Meiling.V1.Session.setExtendedAuthenticationSession(req, undefined);

Meiling.Identity.User.updateLastAuthenticated(userToLogin);
Expand Down

0 comments on commit ab5b416

Please sign in to comment.