mirror of
https://github.com/modrinth/code.git
synced 2026-08-26 17:44:50 +00:00
feat: update auth flow (#5790)
* Backend routes for choosing username in OAuth flow * fix up oauth flow routes * improve URL-related OAuth code * Use user-provided callback addr instead of SELF_ADDR * Revert "Use user-provided callback addr instead of SELF_ADDR" This reverts commit7ea0635d86. * fix flow * fix: backend response for create oauth account * feat: new auth flow (#5840) * update auth with new designs * refactor: auth.js to auth.ts * refactor: componentize auth pages * fix: auth pages height * feat: initial implementation of new sign-in oauth * fix create account flow * fix checkbox * remove hard coded username * implement create user validation endpoint and add more specific error responses * feat: implement under 13 DOB guard and email/password validation route * fix: TOCTOU issue * refactor: pnpm prepr * fix: make sure staging uses staging * fix: hcaptcha styles * fix: copy * remove: auth/welcome page as its no longer used * refactor: bring root page card styles into individual components and use tailwind * fix: account settings modals to use new modal and fix lots of bad styles * refactor: pnpm prepr * feat: implement last signed in indicator * fix: append number when generated name from email is taken * refactor: pnpm prepr * fix: last sign in badge color * fix: qa issues * refactor: pnpm prepr * fix: hover effect on native date picker * chore: temp staging undo * Revert "chore: temp staging undo" This reverts commitcad6bd4f92. * feat: handle app create account * fix: last signed in style * fix: add initOnMounted for SSR race * refactor: use typescript * refactor: pnpm prepr * refactor: use typescript for reset-password * refactor: convert verify-email to use typescript * refactor: convert authorize.vue to use typescript * fix: authorize.vue error states * feat: small style updates * feat: implement date picker component * feat: improve UX and styles for range select * refactor: pnpm prepr * fix: range select border styles * feat: implement date picker component in create account * feat: implement preserve date for date picker * update rust toolchain * increase recursion limit * fix: date picker can be null * fix: calculate age based on user's timezone * fix: number input icons color * fix: date picker icons * feat: improve styles * fix: add width on date * fix: hover color bad on number input * fix lints * feat: add default date open view * fmt * fix: account.vue * fix: remove default date to open 13 years ago * fix: edit copy on info banner * fix: cannot hover over project card tooltip items (#6071) fix: cannot hover over project cards * feat: improve add dependency flow (#6075) * fix: shadow on nav * feat: improve add dependency flow * feat: update suggested dependency style * feat: update dependency rows to use version number and update styles * feat: implement combobox select searched text on focus * feat: add Tabs.vue * feat: update nav tabs to use tabs * feat: improve project search dropdown * fix: dependency search not clearing inbound query * fix: combobox no options open state bug * feat: improve dependency project and version search * fix: open modrinth project links in the app (#6072) * pin tanstack versions + set pnpm min age to 7 days * squash commits * fix: 2 factor auth enter code screen styles * update copy * update copy * improve reset password * feat: update sign in screen * fix: unused import * Merge branch 'main' into boris/dev-908-backend-changes * Revert "Merge branch 'main' into boris/dev-908-backend-changes" This reverts commitb9b03796e3. * fix: add stroke * feat: add passkey support (#6375) * feat: add passkey backend * feat: passkey frontend * invalidate sessions on compromised passkey * chore: run sqlx prepare * fix: make passkey button use both collumns to prevent empty space * fix: correctly verify max passkeys in finish route * fix: use structs for response * fix: add rp name default * style: use web::Json * fmt * feat: improve manage passkeys UI * fix copy * pnpm prepr --------- Co-authored-by: tdgao <mr.trumgao@gmail.com> Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com> Co-authored-by: Michael H. <michael@iptables.sh> Co-authored-by: Calum H. (IMB11) <contact@cal.engineer> Co-authored-by: Calum H. <calum@modrinth.com> Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com> Co-authored-by: DeDiamondPro <67508414+DeDiamondPro@users.noreply.github.com>
This commit is contained in:
co-authored by
tdgao
Truman Gao
Michael H.
Calum H.
Calum H.
Prospector
DeDiamondPro
parent
6fc741f7c0
commit
ef4044534f
@@ -0,0 +1,95 @@
|
||||
function ensurePasskeySupported() {
|
||||
const supported =
|
||||
typeof window !== 'undefined' &&
|
||||
typeof window.PublicKeyCredential !== 'undefined' &&
|
||||
typeof navigator !== 'undefined' &&
|
||||
!!navigator.credentials
|
||||
if (!supported) {
|
||||
throw new Error('Passkeys are not supported by this browser.')
|
||||
}
|
||||
}
|
||||
|
||||
function base64urlToBuffer(base64url: string) {
|
||||
return Uint8Array.from(atob(base64url.replace(/-/g, '+').replace(/_/g, '/')), (char) =>
|
||||
char.charCodeAt(0),
|
||||
)
|
||||
}
|
||||
|
||||
function bufferToBase64url(buffer: ArrayBuffer) {
|
||||
const bytes = new Uint8Array(buffer)
|
||||
let str = ''
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
str += String.fromCharCode(bytes[i])
|
||||
}
|
||||
return btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a passkey credential using the browser's WebAuthn API.
|
||||
*
|
||||
* @param options The public key options for creating the passkey credential, provided by the server.
|
||||
*/
|
||||
export async function createPasskeyCredential(options: any) {
|
||||
ensurePasskeySupported()
|
||||
|
||||
const publicKey = {
|
||||
...options,
|
||||
challenge: base64urlToBuffer(options.challenge),
|
||||
user: {
|
||||
...options.user,
|
||||
id: base64urlToBuffer(options.user.id),
|
||||
},
|
||||
excludeCredentials: options.excludeCredentials?.map((cred: any) => ({
|
||||
...cred,
|
||||
id: base64urlToBuffer(cred.id),
|
||||
})),
|
||||
}
|
||||
|
||||
const credential = (await navigator.credentials.create({ publicKey })) as PublicKeyCredential
|
||||
const response = credential.response as AuthenticatorAttestationResponse
|
||||
|
||||
return {
|
||||
id: credential.id,
|
||||
rawId: bufferToBase64url(credential.rawId),
|
||||
type: credential.type,
|
||||
response: {
|
||||
clientDataJSON: bufferToBase64url(response.clientDataJSON),
|
||||
attestationObject: bufferToBase64url(response.attestationObject),
|
||||
},
|
||||
extensions: credential.getClientExtensionResults(),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticates a user using a passkey credential.
|
||||
*
|
||||
* @param options The public key options for authenticating the passkey credential, provided by the server.
|
||||
*/
|
||||
export async function getPasskeyCredential(options: any) {
|
||||
ensurePasskeySupported()
|
||||
|
||||
const publicKey = {
|
||||
...options,
|
||||
challenge: base64urlToBuffer(options.challenge),
|
||||
allowCredentials: options.allowCredentials?.map((cred: any) => ({
|
||||
...cred,
|
||||
id: base64urlToBuffer(cred.id),
|
||||
})),
|
||||
}
|
||||
|
||||
const credential = (await navigator.credentials.get({ publicKey })) as PublicKeyCredential
|
||||
const response = credential.response as AuthenticatorAssertionResponse
|
||||
|
||||
return {
|
||||
id: credential.id,
|
||||
rawId: bufferToBase64url(credential.rawId),
|
||||
type: credential.type,
|
||||
response: {
|
||||
clientDataJSON: bufferToBase64url(response.clientDataJSON),
|
||||
authenticatorData: bufferToBase64url(response.authenticatorData),
|
||||
signature: bufferToBase64url(response.signature),
|
||||
userHandle: response.userHandle ? bufferToBase64url(response.userHandle) : null,
|
||||
},
|
||||
extensions: credential.getClientExtensionResults(),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user