Quickstarts · vue
Vue 3 — Hub login with `oidc-client-ts`
Wire OAuth2 / OIDC into a Vue 3 + Vite app. Auth code with PKCE, composable for the rest of the app.
- vue
- vite
- oidc
- spa
- pkce
Tested against:framework: Vue 3.4 + Vite 5oidcClient: oidc-client-ts@3.0.0
Prereqs
- Vue 3 + Vite 5
- A Thoryn account
Step 1 — Register a SPA client
hub clients create \
--name "My Vue app" \
--redirect-uri "http://localhost:5173/callback" \
--grant-types authorization_code,refresh_token \
--client-type public \
--pkce required \
--scopes "openid email profile"Step 2 — Install
npm install oidc-client-tsStep 3 — Composable
src/composables/useAuth.ts:
import { ref } from "vue";
import { UserManager, WebStorageStateStore, type User } from "oidc-client-ts";
const userManager = new UserManager({
authority: "https://hub.thoryn.org",
client_id: import.meta.env.VITE_THORYN_CLIENT_ID,
redirect_uri: window.location.origin + "/callback",
scope: "openid email profile",
response_type: "code",
userStore: new WebStorageStateStore({ store: window.localStorage }),
});
const user = ref<User | null>(null);
export function useAuth() {
return {
user,
signIn: () => userManager.signinRedirect(),
signOut: () => userManager.signoutRedirect(),
handleCallback: async () => {
user.value = await userManager.signinRedirectCallback();
},
refresh: async () => {
user.value = await userManager.getUser();
},
};
}Step 4 — Wire it into App.vue
<script setup>
import { onMounted } from "vue";
import { useAuth } from "./composables/useAuth";
const { user, signIn, signOut, handleCallback, refresh } = useAuth();
onMounted(async () => {
if (window.location.pathname === "/callback") {
await handleCallback();
window.history.replaceState({}, "", "/");
} else {
await refresh();
}
});
</script>
<template>
<button v-if="!user" @click="signIn">Sign in</button>
<div v-else>
<p>Hello, {{ user.profile.name }}</p>
<button @click="signOut">Sign out</button>
</div>
</template>Step 5 — Run it
VITE_THORYN_CLIENT_ID=... npm run devWhat's next
Troubleshooting
- Reactivity quirks:
oidc-client-tsreturns plain objects. Wrap them inrefif you need deep reactivity.