♻️ Refactored the auth flow
This commit is contained in:
@@ -11,28 +11,6 @@ export const useSolarNetwork = (withoutProxy = false) => {
|
|||||||
onRequest: ({ request, options }) => {
|
onRequest: ({ request, options }) => {
|
||||||
const side = process.server ? "SERVER" : "CLIENT"
|
const side = process.server ? "SERVER" : "CLIENT"
|
||||||
console.log(`[useSolarNetwork] onRequest for ${request} on ${side}`)
|
console.log(`[useSolarNetwork] onRequest for ${request} on ${side}`)
|
||||||
// Get token from user store
|
|
||||||
const userStore = useUserStore()
|
|
||||||
const token = userStore.token
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
console.log(
|
|
||||||
"[useSolarNetwork] Token found, adding Authorization header."
|
|
||||||
)
|
|
||||||
if (!options.headers) {
|
|
||||||
options.headers = new Headers()
|
|
||||||
}
|
|
||||||
if (options.headers instanceof Headers) {
|
|
||||||
options.headers.set("Authorization", `Bearer ${token}`)
|
|
||||||
} else {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
;(options.headers as any)["Authorization"] = `Bearer ${token}`
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log(
|
|
||||||
"[useSolarNetwork] No token found, skipping Authorization header."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform request data from camelCase to snake_case
|
// Transform request data from camelCase to snake_case
|
||||||
if (options.body && typeof options.body === "object") {
|
if (options.body && typeof options.body === "object") {
|
||||||
|
@@ -201,7 +201,8 @@ async function exchangeToken() {
|
|||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
const tokenResponse = await api<{ token: string }>("/id/auth/token", {
|
// The token endpoint gives the Set-Cookie header
|
||||||
|
await api<{ token: string }>("/id/auth/token", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: {
|
body: {
|
||||||
grant_type: "authorization_code",
|
grant_type: "authorization_code",
|
||||||
@@ -209,11 +210,6 @@ async function exchangeToken() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Store the token in localStorage via user store
|
|
||||||
if (tokenResponse && tokenResponse.token) {
|
|
||||||
userStore.setToken(tokenResponse.token)
|
|
||||||
}
|
|
||||||
|
|
||||||
await userStore.fetchUser()
|
await userStore.fetchUser()
|
||||||
|
|
||||||
const redirectUri = route.query.redirect_uri as string
|
const redirectUri = route.query.redirect_uri as string
|
||||||
@@ -374,14 +370,14 @@ const colorMode = useColorMode()
|
|||||||
factor.type === 0
|
factor.type === 0
|
||||||
? "mdi-lock"
|
? "mdi-lock"
|
||||||
: factor.type === 1
|
: factor.type === 1
|
||||||
? "mdi-email"
|
? "mdi-email"
|
||||||
: factor.type === 2
|
: factor.type === 2
|
||||||
? "mdi-cellphone"
|
? "mdi-cellphone"
|
||||||
: factor.type === 3
|
: factor.type === 3
|
||||||
? "mdi-clock"
|
? "mdi-clock"
|
||||||
: factor.type === 4
|
: factor.type === 4
|
||||||
? "mdi-numeric"
|
? "mdi-numeric"
|
||||||
: "mdi-shield-key"
|
: "mdi-shield-key"
|
||||||
}}</v-icon>
|
}}</v-icon>
|
||||||
</template>
|
</template>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
@@ -1,24 +1,24 @@
|
|||||||
import { useUserStore } from '~/stores/user'
|
import { useUserStore } from "~/stores/user"
|
||||||
|
|
||||||
export default defineNuxtPlugin(() => {
|
export default defineNuxtPlugin(() => {
|
||||||
const side = process.server ? 'SERVER' : 'CLIENT'
|
const side = process.server ? "SERVER" : "CLIENT"
|
||||||
console.log(`[AUTH PLUGIN] Running on ${side}`)
|
console.log(`[AUTH PLUGIN] Running on ${side}`)
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
// Prevent fetching if it's already in progress
|
// Prevent fetching if it's already in progress
|
||||||
if (userStore.isLoading) {
|
if (userStore.isLoading) {
|
||||||
console.log(`[AUTH PLUGIN] User fetch already in progress on ${side}. Skipping.`)
|
console.log(
|
||||||
|
`[AUTH PLUGIN] User fetch already in progress on ${side}. Skipping.`
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// On initial app load, fetch the user if a token exists but the user object isn't populated.
|
// On initial app load, fetch the user if a token exists but the user object isn't populated.
|
||||||
if (userStore.token && !userStore.user) {
|
if (!userStore.user) {
|
||||||
console.log(`[AUTH PLUGIN] Token found, user not loaded. Fetching user on ${side}.`)
|
console.log(
|
||||||
|
`[AUTH PLUGIN] User not loaded. Trying to fetching user on ${side}.`
|
||||||
|
)
|
||||||
userStore.fetchUser()
|
userStore.fetchUser()
|
||||||
} else {
|
|
||||||
console.log(`[AUTH PLUGIN] Conditions not met for fetching user on ${side}.`, {
|
|
||||||
hasToken: !!userStore.token,
|
|
||||||
hasUser: !!userStore.user
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -10,15 +10,8 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const error = ref<string | null>(null)
|
const error = ref<string | null>(null)
|
||||||
|
|
||||||
// The name is match with the remote one (set by server Set-Cookie)
|
|
||||||
const token = useCookie<string | null>("fl_AuthToken", {
|
|
||||||
default: () => null,
|
|
||||||
path: "/",
|
|
||||||
maxAge: 60 * 60 * 24 * 365 * 10
|
|
||||||
}) // 10 years
|
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
const isAuthenticated = computed(() => !!user.value && !!token.value)
|
const isAuthenticated = computed(() => !!user.value)
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
async function fetchUser(reload = true) {
|
async function fetchUser(reload = true) {
|
||||||
@@ -32,7 +25,7 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
const response = await api("/id/accounts/me")
|
const response = await api("/id/accounts/me")
|
||||||
|
|
||||||
user.value = response as SnAccount
|
user.value = response as SnAccount
|
||||||
console.log(`Logged in as ${user.value.name}`)
|
console.log(`[UserStore] Logged in as ${user.value.name}`)
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
if (e instanceof FetchError && e.statusCode == 401) {
|
if (e instanceof FetchError && e.statusCode == 401) {
|
||||||
error.value = "Unauthorized"
|
error.value = "Unauthorized"
|
||||||
@@ -47,23 +40,16 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setToken(newToken: string) {
|
|
||||||
token.value = newToken
|
|
||||||
}
|
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
user.value = null
|
user.value = null
|
||||||
token.value = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
token,
|
|
||||||
isLoading,
|
isLoading,
|
||||||
error,
|
error,
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
fetchUser,
|
fetchUser,
|
||||||
setToken,
|
|
||||||
logout
|
logout
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user