diff --git a/.gitignore b/.gitignore index 136e5a0..e1e7a1b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ dist/ !.gitignore *.lock *.db -server-secret.bin \ No newline at end of file +server-secret.bin +/passkeyauth/frontend-static diff --git a/frontend/bun.lockb b/frontend/bun.lockb deleted file mode 100755 index b188daa..0000000 Binary files a/frontend/bun.lockb and /dev/null differ diff --git a/frontend/index.html b/frontend/index.html index b19040a..ddb2818 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,9 +2,9 @@ - + - Vite App + Passkey Authentication
diff --git a/frontend/package.json b/frontend/package.json index ba4d74d..2d61b90 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,7 +16,6 @@ }, "devDependencies": { "@vitejs/plugin-vue": "^6.0.0", - "vite": "^7.0.4", - "vite-plugin-vue-devtools": "^7.7.7" + "vite": "^7.0.4" } } diff --git a/frontend/src/assets/icon.webp b/frontend/src/assets/icon.webp new file mode 100644 index 0000000..9983df6 Binary files /dev/null and b/frontend/src/assets/icon.webp differ diff --git a/frontend/src/stores/auth.js b/frontend/src/stores/auth.js index 38a136d..b008bcb 100644 --- a/frontend/src/stores/auth.js +++ b/frontend/src/stores/auth.js @@ -1,6 +1,5 @@ import { defineStore } from 'pinia' import { registerUser, authenticateUser, registerWithToken } from '@/utils/passkey' -import aWebSocket from '@/utils/awaitable-websocket' export const useAuthStore = defineStore('auth', { state: () => ({ @@ -102,18 +101,6 @@ export const useAuthStore = defineStore('auth', { this.isLoading = false } }, - async addNewCredential() { - this.isLoading = true; - try { - const result = await registerWithToken() - await this.loadCredentials() - return result; - } catch (error) { - throw new Error(`Failed to add new credential: ${error.message}`) - } finally { - this.isLoading = false - } - }, async deleteCredential(credentialId) { const response = await fetch('/auth/delete-credential', { method: 'POST', @@ -138,24 +125,5 @@ export const useAuthStore = defineStore('auth', { this.currentCredentials = [] this.aaguidInfo = {} }, - async checkResetCookieAndRegister() { - const passphrase = getCookie('reset') - if (passphrase) { - // Abandon existing session - await fetch('/auth/logout', { method: 'POST', credentials: 'include' }) - - // Register additional token for the user - try { - const result = await registerUserFromCookie() - await this.setSessionCookie(result.session_token) - this.currentUser = { - user_id: result.user_id, - user_name: result.user_name, - } - } catch (error) { - console.error('Failed to register additional token:', error) - } - } - }, } }) diff --git a/frontend/src/utils/passkey.js b/frontend/src/utils/passkey.js index 0a74dea..0d98e3e 100644 --- a/frontend/src/utils/passkey.js +++ b/frontend/src/utils/passkey.js @@ -22,7 +22,7 @@ export async function registerCredential() { return register('/auth/ws/add_credential') } export async function registerWithToken(token) { - return register('/auth/ws/add_device_credential', {token}) + return register('/auth/ws/add_device_credential', { token }) } export async function authenticateUser() { diff --git a/frontend/vite.config.js b/frontend/vite.config.js index dad8e01..0749d1e 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -2,19 +2,18 @@ import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' -import vueDevTools from 'vite-plugin-vue-devtools' // https://vite.dev/config/ export default defineConfig({ plugins: [ vue(), - vueDevTools(), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) }, }, + base: '/auth/', server: { port: 3000, proxy: { @@ -26,7 +25,7 @@ export default defineConfig({ } }, build: { - outDir: '../static/dist', + outDir: '../passkeyauth/frontend-static', emptyOutDir: true, assetsDir: 'assets' } diff --git a/passkeyauth/main.py b/passkeyauth/main.py index 970d9ce..5e9c339 100644 --- a/passkeyauth/main.py +++ b/passkeyauth/main.py @@ -39,8 +39,7 @@ from .passkey import Passkey from .reset_handlers import create_device_addition_link, validate_device_addition_token from .session_manager import get_user_from_cookie_string -STATIC_DIR = Path(__file__).parent.parent / "static" - +STATIC_DIR = Path(__file__).parent / "frontend-static" passkey = Passkey( rp_id="localhost", @@ -213,7 +212,7 @@ async def websocket_authenticate(ws: WebSocket): await ws.accept() origin = ws.headers.get("origin") try: - options, challenge = passkey.auth_generate_options(origin=origin) + options, challenge = passkey.auth_generate_options() await ws.send_json(options) # Wait for the client to use his authenticator to authenticate credential = passkey.auth_parse(await ws.receive_json()) @@ -331,13 +330,23 @@ async def api_get_user_info_by_passphrase(token: str): # Serve static files -app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static") +app.mount( + "/auth/assets", StaticFiles(directory=STATIC_DIR / "assets"), name="static assets" +) + + +@app.get("/auth") +async def redirect_to_index(): + """Serve the main authentication app.""" + return FileResponse(STATIC_DIR / "index.html") # Catch-all route for SPA - serve index.html for all non-API routes @app.get("/{path:path}") -async def spa_handler(path: str): +async def spa_handler(request: Request, path: str): """Serve the Vue SPA for all routes (except API and static)""" + if "text/html" not in request.headers.get("accept", ""): + return Response(content="Not Found", status_code=404) return FileResponse(STATIC_DIR / "index.html")