feat: TOTP (two-factor) Authentication (#55)
* Working on some initial prototype stuff for TOTP * Fixed a bug that prevented the change password menu from working * Enable/disable totp working * Added the new login procedure including TOTP! :) * misc: Changed bad description for the TOTP_SECRET env var * I forgot to include the migration for the new prisma stuff * fix: refresh user context instead refreshing the page * refactor: simplify totp error handling * Removed U2F tab + format schema * fix: tokens not saved in cookies * refactor: deleted commented out code * refactor: move password text to input description * refactor: remove tabler icon package Co-authored-by: Elias Schneider <login@eliasschneider.com> Co-authored-by: Elias Schneider <58886915+stonith404@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { getCookie, setCookies } from "cookies-next";
|
||||
import { getCookie, setCookie } from "cookies-next";
|
||||
import * as jose from "jose";
|
||||
import api from "./api.service";
|
||||
|
||||
@@ -11,8 +11,25 @@ const signIn = async (emailOrUsername: string, password: string) => {
|
||||
...emailOrUsernameBody,
|
||||
password,
|
||||
});
|
||||
setCookies("access_token", response.data.accessToken);
|
||||
setCookies("refresh_token", response.data.refreshToken);
|
||||
return response;
|
||||
};
|
||||
|
||||
const signInTotp = async (
|
||||
emailOrUsername: string,
|
||||
password: string,
|
||||
totp: string,
|
||||
loginToken: string
|
||||
) => {
|
||||
const emailOrUsernameBody = emailOrUsername.includes("@")
|
||||
? { email: emailOrUsername }
|
||||
: { username: emailOrUsername };
|
||||
|
||||
const response = await api.post("auth/signIn/totp", {
|
||||
...emailOrUsernameBody,
|
||||
password,
|
||||
totp,
|
||||
loginToken,
|
||||
});
|
||||
return response;
|
||||
};
|
||||
|
||||
@@ -21,8 +38,8 @@ const signUp = async (email: string, username: string, password: string) => {
|
||||
};
|
||||
|
||||
const signOut = () => {
|
||||
setCookies("access_token", null);
|
||||
setCookies("refresh_token", null);
|
||||
setCookie("access_token", null);
|
||||
setCookie("refresh_token", null);
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
@@ -37,7 +54,7 @@ const refreshAccessToken = async () => {
|
||||
const refreshToken = getCookie("refresh_token");
|
||||
|
||||
const response = await api.post("auth/token", { refreshToken });
|
||||
setCookies("access_token", response.data.accessToken);
|
||||
setCookie("access_token", response.data.accessToken);
|
||||
}
|
||||
} catch {
|
||||
console.info("Refresh token invalid or expired");
|
||||
@@ -48,10 +65,38 @@ const updatePassword = async (oldPassword: string, password: string) => {
|
||||
await api.patch("/auth/password", { oldPassword, password });
|
||||
};
|
||||
|
||||
const enableTOTP = async (password: string) => {
|
||||
const { data } = await api.post("/auth/totp/enable", { password });
|
||||
|
||||
return {
|
||||
totpAuthUrl: data.totpAuthUrl,
|
||||
totpSecret: data.totpSecret,
|
||||
qrCode: data.qrCode,
|
||||
};
|
||||
};
|
||||
|
||||
const verifyTOTP = async (totpCode: string, password: string) => {
|
||||
await api.post("/auth/totp/verify", {
|
||||
code: totpCode,
|
||||
password,
|
||||
});
|
||||
};
|
||||
|
||||
const disableTOTP = async (totpCode: string, password: string) => {
|
||||
await api.post("/auth/totp/disable", {
|
||||
code: totpCode,
|
||||
password,
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
signIn,
|
||||
signInTotp,
|
||||
signUp,
|
||||
signOut,
|
||||
refreshAccessToken,
|
||||
updatePassword,
|
||||
enableTOTP,
|
||||
verifyTOTP,
|
||||
disableTOTP,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user