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")