Skip to main content

Custom Implementation

If you prefer full control over how app routes are secured, you can build a custom solution using the primitives provided by the ThunderID Vue SDK. This helps when you need to run custom application logic before enabling or disabling a route.

Basic Custom Route Guard With <SignedIn />

The simplest approach is to wrap the protected page content with the <SignedIn /> component and render a fallback for unauthenticated users:

src/pages/Contact.vue
<script setup>
import { SignedIn, SignedOut } from '@thunderid/vue'
import ContactDetails from '../components/ContactDetails.vue'
</script>

<template>
<SignedIn>
<ContactDetails />
</SignedIn>
<SignedOut>
<p>You must sign in to view this page.</p>
</SignedOut>
</template>

Custom Composable Using useThunderID

For more advanced control — for example, role-based protection or a redirect — use useThunderID() together with Vue Router's useRouter:

src/composables/useRequireAuth.ts
import { watchEffect } from 'vue'
import { useRouter } from 'vue-router'
import { useThunderID } from '@thunderid/vue'

export interface RequireAuthOptions {
redirectTo?: string
requireRole?: string
}

export function useRequireAuth(options: RequireAuthOptions = {}) {
const { redirectTo = '/signin', requireRole } = options
const { isInitialized, isSignedIn, user } = useThunderID()
const router = useRouter()

watchEffect(() => {
if (!isInitialized.value) return

if (!isSignedIn.value) {
router.replace(redirectTo)
return
}

if (requireRole && !user.value?.roles?.includes(requireRole)) {
router.replace('/forbidden')
}
})
}

Then use it inside any protected page:

src/pages/AdminDashboard.vue
<script setup>
import { useRequireAuth } from '../composables/useRequireAuth'

useRequireAuth({ redirectTo: '/signin', requireRole: 'admin' })
</script>

<template>
<h1>Admin Dashboard</h1>
<!-- ... -->
</template>

Custom Navigation Guard

You can also build a Vue Router navigation guard from scratch using the SDK's inject key directly. This is essentially what createThunderIDGuard does internally, and you can fork it to add custom logic.

src/router/guards.ts
import { inject } from 'vue'
import type { NavigationGuard } from 'vue-router'
import { THUNDERID_KEY } from '@thunderid/vue'
import type { ThunderIDContext } from '@thunderid/vue'

export const requireAuth: NavigationGuard = async (to, from, next) => {
const ctx = inject<ThunderIDContext>(THUNDERID_KEY)

if (!ctx) {
return next({ path: '/signin' })
}

// Wait for initialization
while (!ctx.isInitialized.value) {
await new Promise((resolve) => requestAnimationFrame(resolve))
}

if (!ctx.isSignedIn.value) {
return next({ path: '/signin', query: { redirect: to.fullPath } })
}

// Add any custom role / permission checks here

return next()
}
ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© WSO2 LLC. All rights reserved.Privacy PolicyCookie Policy