enhance: user token storage

This commit is contained in:
Jacky 2024-10-23 11:48:58 +08:00
parent 925e61abf4
commit 59947a35db
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
5 changed files with 66 additions and 48 deletions

View file

@ -46,7 +46,7 @@ async function passkeyAuthenticate() {
passkeyLoading.value = true passkeyLoading.value = true
try { try {
const begin = await twoFA.begin_start_secure_session_by_passkey() const begin = await twoFA.begin_start_secure_session_by_passkey()
const asseResp = await startAuthentication(begin.options.publicKey) const asseResp = await startAuthentication({ optionsJSON: begin.options.publicKey })
const r = await twoFA.finish_start_secure_session_by_passkey({ const r = await twoFA.finish_start_secure_session_by_passkey({
session_id: begin.session_id, session_id: begin.session_id,

View file

@ -1,6 +1,5 @@
import { createVNode, render } from 'vue' import { createVNode, render } from 'vue'
import { Modal, message } from 'ant-design-vue' import { Modal, message } from 'ant-design-vue'
import { useCookies } from '@vueuse/integrations/useCookies'
import Authorization from '@/components/TwoFA/Authorization.vue' import Authorization from '@/components/TwoFA/Authorization.vue'
import twoFA from '@/api/2fa' import twoFA from '@/api/2fa'
import { useUserStore } from '@/pinia' import { useUserStore } from '@/pinia'
@ -32,11 +31,8 @@ const use2FAModal = () => {
return return
} }
const cookies = useCookies(['nginx-ui-2fa']) if (secureSessionId.value && secureSessionStatus) {
const ssid = cookies.get('secure_session_id') resolve(secureSessionId.value)
if (ssid && secureSessionStatus) {
resolve(ssid)
secureSessionId.value = ssid
return return
} }
@ -51,7 +47,6 @@ const use2FAModal = () => {
} }
const setSessionId = (sessionId: string) => { const setSessionId = (sessionId: string) => {
cookies.set('secure_session_id', sessionId, { maxAge: 60 * 3 })
close() close()
secureSessionId.value = sessionId secureSessionId.value = sessionId
resolve(sessionId) resolve(sessionId)

View file

@ -1,6 +1,5 @@
import type { AxiosRequestConfig } from 'axios' import type { AxiosRequestConfig } from 'axios'
import axios from 'axios' import axios from 'axios'
import { useCookies } from '@vueuse/integrations/useCookies'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import NProgress from 'nprogress' import NProgress from 'nprogress'
import { useSettingsStore, useUserStore } from '@/pinia' import { useSettingsStore, useUserStore } from '@/pinia'
@ -62,10 +61,9 @@ instance.interceptors.response.use(
NProgress.done() NProgress.done()
const otpModal = use2FAModal() const otpModal = use2FAModal()
const cookies = useCookies(['nginx-ui-2fa'])
switch (error.response.status) { switch (error.response.status) {
case 401: case 401:
cookies.remove('secure_session_id') secureSessionId.value = ''
await otpModal.open() await otpModal.open()
break break
case 403: case 403:

View file

@ -1,34 +1,64 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { useCookies } from '@vueuse/integrations/useCookies'
import type { CookieChangeOptions } from 'universal-cookie'
export const useUserStore = defineStore('user', { export const useUserStore = defineStore('user', () => {
state: () => ({ const cookies = useCookies(['nginx-ui'])
token: '',
unreadCount: 0, const token = ref('')
secureSessionId: '',
passkeyRawId: '', watch(token, v => {
}), cookies.set('token', v, { maxAge: 86400 })
getters: { })
isLogin(state): boolean {
return !!state.token const secureSessionId = ref('')
},
passkeyLoginAvailable(state): boolean { watch(secureSessionId, v => {
return !!state.passkeyRawId cookies.set('secure_session_id', v, { maxAge: 60 * 3 })
}, })
},
actions: { function handleCookieChange({ name, value }: CookieChangeOptions) {
passkeyLogin(rawId: string, token: string) { if (name === 'token')
this.passkeyRawId = rawId token.value = value
this.login(token) else if (name === 'secure_session_id')
}, secureSessionId.value = value
login(token: string) { }
this.token = token
}, cookies.addChangeListener(handleCookieChange)
logout() {
this.token = '' const passkeyRawId = ref('')
this.passkeyRawId = ''
this.secureSessionId = '' const unreadCount = ref(0)
this.unreadCount = 0 const isLogin = computed(() => !!token.value)
}, const passkeyLoginAvailable = computed(() => !!passkeyRawId.value)
},
function passkeyLogin(rawId: string, tokenValue: string) {
passkeyRawId.value = rawId
login(tokenValue)
}
function login(tokenValue: string) {
token.value = tokenValue
}
function logout() {
token.value = ''
passkeyRawId.value = ''
secureSessionId.value = ''
unreadCount.value = 0
}
return {
token,
unreadCount,
secureSessionId,
passkeyRawId,
isLogin,
passkeyLoginAvailable,
passkeyLogin,
login,
logout,
}
}, {
persist: true, persist: true,
}) })

View file

@ -1,7 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { KeyOutlined, LockOutlined, UserOutlined } from '@ant-design/icons-vue' import { KeyOutlined, LockOutlined, UserOutlined } from '@ant-design/icons-vue'
import { Form, message } from 'ant-design-vue' import { Form, message } from 'ant-design-vue'
import { useCookies } from '@vueuse/integrations/useCookies'
import { startAuthentication } from '@simplewebauthn/browser' import { startAuthentication } from '@simplewebauthn/browser'
import { useUserStore } from '@/pinia' import { useUserStore } from '@/pinia'
import auth from '@/api/auth' import auth from '@/api/auth'
@ -60,13 +59,12 @@ const onSubmit = () => {
await auth.login(modelRef.username, modelRef.password, passcode.value, recoveryCode.value).then(async r => { await auth.login(modelRef.username, modelRef.password, passcode.value, recoveryCode.value).then(async r => {
const next = (route.query?.next || '').toString() || '/' const next = (route.query?.next || '').toString() || '/'
const cookies = useCookies(['nginx-ui-2fa'])
switch (r.code) { switch (r.code) {
case 200: case 200:
message.success($gettext('Login successful'), 1) message.success($gettext('Login successful'), 1)
login(r.token) login(r.token)
await nextTick()
secureSessionId.value = r.secure_session_id secureSessionId.value = r.secure_session_id
cookies.set('secure_session_id', r.secure_session_id, { maxAge: 60 * 3 })
await router.push(next) await router.push(next)
break break
case 199: case 199:
@ -159,7 +157,7 @@ async function handlePasskeyLogin() {
passkeyLoginLoading.value = true passkeyLoginLoading.value = true
try { try {
const begin = await auth.begin_passkey_login() const begin = await auth.begin_passkey_login()
const asseResp = await startAuthentication(begin.options.publicKey) const asseResp = await startAuthentication({ optionsJSON: begin.options.publicKey })
const r = await auth.finish_passkey_login({ const r = await auth.finish_passkey_login({
session_id: begin.session_id, session_id: begin.session_id,
@ -167,13 +165,10 @@ async function handlePasskeyLogin() {
}) })
if (r.token) { if (r.token) {
const cookies = useCookies(['nginx-ui-2fa'])
const next = (route.query?.next || '').toString() || '/' const next = (route.query?.next || '').toString() || '/'
passkeyLogin(asseResp.rawId, r.token) passkeyLogin(asseResp.rawId, r.token)
secureSessionId.value = r.secure_session_id secureSessionId.value = r.secure_session_id
cookies.set('secure_session_id', r.secure_session_id, { maxAge: 60 * 3 })
await router.push(next) await router.push(next)
} }
} }