Introducing vue-oidc-context – OIDC & OAuth 2.0 for Vue 3

If you’ve used react-oidc-context in a React app, you already know the appeal: a thin, predictable wrapper around oidc-client-ts that turns the OIDC / OAuth 2.0 protocol into clean, reactive state. For a long time Vue 3 had nothing quite like it – so I built vue-oidc-context, a deliberate port of react-oidc-context v3 that keeps the same option names, the same lifecycle, and the same callbacks, but exposes them the way Vue wants: a plugin, composables, renderless components, and a vue-router guard.

The short version

vue-oidc-context is OpenID Connect & OAuth 2.0 authentication for Vue 3 – a lightweight, fully typed bridge from oidc-client-ts into Vue’s reactivity system. All the real protocol work (authorization code + PKCE, token storage, silent renewal, session monitoring) stays in oidc-client-ts. This library just makes it reactive and Vue-idiomatic.

One detail up front: it’s published as @dlukt/vue-oidc-context on npm. The unscoped name vue-oidc-context belongs to an unrelated package, so install the scoped one.

Install

oidc-client-ts is a peer dependency, so it installs as its own package. Requirements: Vue 3.5+, oidc-client-ts 3.3+, and Node 20+. vue-router 4.2+ is optional – you only need it for the route guard.

Set it up once

Create the auth instance and install it as a plugin:

That options object is flat – UserManagerSettings plus a handful of callbacks side by side. If you’re coming from react-oidc-context, your existing config object works unchanged.

Use it anywhere with useAuth()

useAuth() returns reactive refs – user, isAuthenticated, isLoading, activeNavigator, and error – plus the full UserManager surface: signinRedirect, signinPopup, signinSilent, signoutRedirect, removeUser, clearStaleState, revokeTokens, startSilentRenew, stopSilentRenew, the raw events bus, and more.

Reactivity tip: destructure the fields you need. If you keep the whole object (const auth = useAuth()), nested refs don’t unwrap in templates and you’d have to write auth.user.value. Destructuring sidesteps that entirely.

Protect routes with the guard

By default it protects any route with meta: { requiresAuth: true }, awaits auth.initialized so there’s no redirect loop, and preserves the return path in signinArgs. Not using vue-router? Drop in the <AuthenticationRequired> component to guard a subtree instead.

Why this exists

Vue has auth options, but I wanted exactly the react-oidc-context experience: a thin layer that doesn’t hide the protocol, a config object I recognize, and upstream docs that still apply. So the move from React is mostly mechanical:

react-oidc-context vue-oidc-context
<AuthProvider {…config}> app.use(createOidcAuth(config))
useAuth() useAuth() (same name; refs to destructure)
withAuthenticationRequired(…) createAuthGuard(auth) or <AuthenticationRequired>
useAutoSignin() useAutoSignin()
hasAuthParams() hasAuthParams()

Same option names, same lifecycle, same callbacks. Copy your config and keep reading the oidc-client-ts / react-oidc-context docs.

What you get

  • Authorization Code flow with PKCE (via oidc-client-ts)
  • Silent renewal – refresh-token based when you request offline_access (no third-party cookies needed), or hidden-iframe otherwise
  • A typed events bus (addAccessTokenExpiring, addUserLoaded, …)
  • Multiple navigators: redirect, popup, silent, and resource-owner-credentials sign-in
  • useAutoSignin() for automatic sign-in
  • Renderless <AuthProvider> for nested / multi-IdP setups
  • Strict TypeScript throughout, types sourced from oidc-client-ts
  • SSR-safe by construction – importing it never touches window

A note on SSR

It’s SSR-safe out of the box: importing any entry point is side-effect-free and never touches window/document; environment detection happens at construction time. On the server, createOidcAuth() yields an inert context – user stays undefined, isLoading stays true, and navigators reject with a clear “only available in a browser” error. There’s a Nuxt recipe (client-only plugin) in the docs, with a proper Nuxt module on the roadmap.

Try it

There’s a playground in the repo – clone it, run pnpm play, and log in against the public Duende demo IdP. Full docs live at dlukt.github.io/vue-oidc-context, including a migration guide and an API reference.

Honest caveat

It’s at 0.1.0 – brand new. The API is stable in intent, but treat it as early. I’d love feedback, bug reports, and weird edge cases.

MIT-licensed, on GitHub and npm as @dlukt/vue-oidc-context. If you’re porting an app off React or just adding OIDC to a Vue project, give it a spin and tell me what breaks.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.