Browse Source

expire pending login

pull/2671/head
Bernd Storath 3 weeks ago
parent
commit
fdfb7bd7fb
  1. 8
      src/app/pages/login/2fa.vue
  2. 3
      src/i18n/locales/en.json
  3. 2
      src/server/api/auth/[provider]/callback.get.ts
  4. 4
      src/server/api/auth/cancel.post.ts
  5. 2
      src/server/api/auth/password.post.ts
  6. 10
      src/server/api/auth/pending.get.ts
  7. 7
      src/server/api/auth/verify-2fa.post.ts
  8. 3
      src/server/utils/session.ts

8
src/app/pages/login/2fa.vue

@ -65,6 +65,14 @@ const _submit = useSubmit(
type: 'error',
});
return;
} else if (data?.status === 'PENDING_LOGIN_EXPIRED') {
toast.showToast({
title: t('general.2fa'),
message: t('login.loginExpired'),
type: 'error',
});
await navigateTo('/login');
return;
}
}
authenticating.value = false;

3
src/i18n/locales/en.json

@ -84,7 +84,8 @@
"rememberMeDesc": "Stay logged after closing the browser",
"insecure": "You can't log in with an insecure connection. Use HTTPS.",
"2faRequired": "Two Factor Authentication is required",
"2faWrong": "Two Factor Authentication is wrong"
"2faWrong": "Two Factor Authentication is wrong",
"loginExpired": "Login expired. Try again"
},
"client": {
"empty": "There are no clients yet.",

2
src/server/api/auth/[provider]/callback.get.ts

@ -40,6 +40,8 @@ export default defineEventHandler(async (event) => {
type: 'oauth',
userId: result.userId,
remember: false,
// 5min
expires_at: Date.now() + 5 * 60 * 1000,
},
oauth_nonce: undefined,
oauth_state: undefined,

4
src/server/api/auth/cancel.post.ts

@ -1,10 +1,12 @@
export default defineEventHandler(async (event) => {
const session = await useWGSession(event, false);
const session = await useWGSession(event);
await session.update({
pendingLogin: undefined,
oauth_nonce: undefined,
oauth_state: undefined,
oauth_verifier: undefined,
});
return { success: true as const };
});

2
src/server/api/auth/password.post.ts

@ -32,6 +32,8 @@ export default defineEventHandler(async (event) => {
type: 'password',
userId: result.userId,
remember,
// 5min
expires_at: Date.now() + 5 * 60 * 1000,
},
});
return { status: 'TOTP_REQUIRED' as const };

10
src/server/api/auth/pending.get.ts

@ -7,6 +7,16 @@ export default defineEventHandler(async (event) => {
statusMessage: 'No pending authentication',
});
}
if (new Date() > new Date(session.data.pendingLogin.expires_at)) {
await session.update({
pendingLogin: undefined,
});
throw createError({
statusCode: 401,
statusMessage: 'No pending authentication',
});
}
return {
type: session.data.pendingLogin.type,

7
src/server/api/auth/verify-2fa.post.ts

@ -14,6 +14,13 @@ export default defineEventHandler(async (event) => {
statusMessage: 'No pending authentication',
});
}
if (new Date() > new Date(pendingLogin.expires_at)) {
await session.update({
pendingLogin: undefined,
});
return { status: 'PENDING_LOGIN_EXPIRED' as const };
}
const totpStatus = await Database.users.validateTotpCode(
pendingLogin.userId,

3
src/server/utils/session.ts

@ -3,11 +3,12 @@ import type { UserType } from '#db/repositories/user/types';
export type WGSession = Partial<{
userId: ID;
// TODO: add pending login expiration
pendingLogin: {
type: 'password' | 'oauth';
userId: ID;
remember: boolean;
/** in milliseconds */
expires_at: number;
};
oauth_verifier: string;
oauth_nonce: string;

Loading…
Cancel
Save