Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/Atinux/nuxt-auth-utils
Minimal Auth module for Nuxt 3.
https://github.com/Atinux/nuxt-auth-utils
authentication nuxt nuxt-auth nuxt-module
Last synced: about 1 month ago
JSON representation
Minimal Auth module for Nuxt 3.
- Host: GitHub
- URL: https://github.com/Atinux/nuxt-auth-utils
- Owner: Atinux
- License: mit
- Created: 2023-10-28T00:30:08.000Z (11 months ago)
- Default Branch: main
- Last Pushed: 2024-04-12T19:04:38.000Z (5 months ago)
- Last Synced: 2024-04-15T14:01:20.620Z (5 months ago)
- Topics: authentication, nuxt, nuxt-auth, nuxt-module
- Language: TypeScript
- Homepage:
- Size: 515 KB
- Stars: 410
- Watchers: 6
- Forks: 39
- Open Issues: 22
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# Nuxt Auth Utils
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]
[![Nuxt][nuxt-src]][nuxt-href]Add Authentication to Nuxt applications with secured & sealed cookies sessions.
- [Release Notes](/CHANGELOG.md)
- [Demo](https://github.com/atinux/nuxt-todos-edge)## Features
- [Hybrid Rendering](#hybrid-rendering) support (SSR / CSR / SWR / Prerendering)
- [15+ OAuth Providers](#supported-oauth-providers)
- [Vue composable](#vue-composable)
- [Server utils](#server-utils)
- [`` component](#authstate-component)
- [Extendable with hooks](#extend-session)It has few dependencies (only from [UnJS](https://github.com/unjs)), run on multiple JS environments (Node, Deno, Workers) and is fully typed with TypeScript.
## Requirements
This module only works with a Nuxt server running as it uses server API routes (`nuxt build`).
This means that you cannot use this module with `nuxt generate`.
You can anyway use [Hybrid Rendering](#hybrid-rendering) to pre-render pages of your application or disable server-side rendering completely.
## Quick Setup
1. Add `nuxt-auth-utils` in your Nuxt project
```bash
npx nuxi@latest module add auth-utils
```2. Add a `NUXT_SESSION_PASSWORD` env variable with at least 32 characters in the `.env`.
```bash
# .env
NUXT_SESSION_PASSWORD=password-with-at-least-32-characters
```Nuxt Auth Utils generates one for you when running Nuxt in development the first time if no `NUXT_SESSION_PASSWORD` is set.
3. That's it! You can now add authentication to your Nuxt app ✨
## Vue Composable
Nuxt Auth Utils automatically adds some plugins to fetch the current user session to let you access it from your Vue components.
### User Session
```vue
const { loggedIn, user, session, fetch, clear } = useUserSession()
Welcome {{ user.login }}!
Logged in since {{ session.loggedInAt }}
Logout
```
**TypeScript Signature:**
```ts
interface UserSessionComposable {
/**
* Computed indicating if the auth session is ready
*/
ready: ComputedRef
/**
* Computed indicating if the user is logged in.
*/
loggedIn: ComputedRef
/**
* The user object if logged in, null otherwise.
*/
user: ComputedRef
/**
* The session object.
*/
session: Ref
/**
* Fetch the user session from the server.
*/
fetch: () => Promise
/**
* Clear the user session and remove the session cookie.
*/
clear: () => Promise
}
```## Server Utils
The following helpers are auto-imported in your `server/` directory.
### Session Management
```ts
// Set a user session, note that this data is encrypted in the cookie but can be decrypted with an API call
// Only store the data that allow you to recognize a user, but do not store sensitive data
// Merges new data with existing data using defu()
await setUserSession(event, {
user: {
// ... user data
},
loggedInAt: new Date()
// Any extra fields
})// Replace a user session. Same behaviour as setUserSession, except it does not merge data with existing data
await replaceUserSession(event, data)// Get the current user session
const session = await getUserSession(event)// Clear the current user session
await clearUserSession(event)// Require a user session (send back 401 if no `user` key in session)
const session = await requireUserSession(event)
```You can define the type for your user session by creating a type declaration file (for example, `auth.d.ts`) in your project to augment the `UserSession` type:
```ts
// auth.d.ts
declare module '#auth-utils' {
interface User {
// Add your own fields
}interface UserSession {
// Add your own fields
}
}export {}
```### OAuth Event Handlers
All handlers can be auto-imported and used in your server routes or API routes.
The pattern is `oauthEventHandler({ onSuccess, config?, onError? })`, example: `oauthGitHubEventHandler`.
The helper returns an event handler that automatically redirects to the provider authorization page and then calls `onSuccess` or `onError` depending on the result.
The `config` can be defined directly from the `runtimeConfig` in your `nuxt.config.ts`:
```ts
export default defineNuxtConfig({
runtimeConfig: {
oauth: {
// provider in lowercase (github, google, etc.)
: {
clientId: '...',
clientSecret: '...'
}
}
}
})
```It can also be set using environment variables:
- `NUXT_OAUTH__CLIENT_ID`
- `NUXT_OAUTH__CLIENT_SECRET`> Provider is in uppercase (GITHUB, GOOGLE, etc.)
#### Supported OAuth Providers
- Auth0
- AWS Cognito
- Battle.net
- Discord
- GitHub
- Keycloak
- Microsoft
- PayPal
- Spotify
- Steam
- Twitch
- X (Twitter)
- XSUAA
- YandexYou can add your favorite provider by creating a new file in [src/runtime/server/lib/oauth/](./src/runtime/server/lib/oauth/).
### Example
Example: `~/server/routes/auth/github.get.ts`
```ts
export default oauthGitHubEventHandler({
config: {
emailRequired: true
},
async onSuccess(event, { user, tokens }) {
await setUserSession(event, {
user: {
githubId: user.id
}
})
return sendRedirect(event, '/')
},
// Optional, will return a json error and 401 status code by default
onError(event, error) {
console.error('GitHub OAuth error:', error)
return sendRedirect(event, '/')
},
})
```Make sure to set the callback URL in your OAuth app settings as `/auth/github`.
### Extend Session
We leverage hooks to let you extend the session data with your own data or log when the user clears the session.
```ts
// server/plugins/session.ts
export default defineNitroPlugin(() => {
// Called when the session is fetched during SSR for the Vue composable (/api/_auth/session)
// Or when we call useUserSession().fetch()
sessionHooks.hook('fetch', async (session, event) => {
// extend User Session by calling your database
// or
// throw createError({ ... }) if session is invalid for example
})// Called when we call useServerSession().clear() or clearUserSession(event)
sessionHooks.hook('clear', async (session, event) => {
// Log that user logged out
})
})
```## Server-Side Rendering
You can make authenticated requests both from the client and the server. However, you must use `useRequestFetch()` to make authenticated requests during SSR if you are not using `useFetch()`
```vue
// When using useAsyncData
const { data } = await useAsyncData('team', () => useRequestFetch()('/api/protected-endpoint'))// useFetch will automatically use useRequestFetch during SSR
const { data } = await useFetch('/api/protected-endpoint')```
> There's [an open issue](https://github.com/nuxt/nuxt/issues/24813) to include credentials in `$fetch` in Nuxt.
## Hybrid Rendering
When using [Nuxt `routeRules`](https://nuxt.com/docs/guide/concepts/rendering#hybrid-rendering) to prerender or cache your pages, Nuxt Auth Utils will not fetch the user session during prerendering but instead fetch it on the client-side (after hydration).
This is because the user session is stored in a secure cookie and cannot be accessed during prerendering.
**This means that you should not rely on the user session during prerendering.**
### `` component
You can use the `` component to safely display auth-related data in your components without worrying about the rendering mode.
One common use case if the Login button in the header:
```vue
Logout
Login
```
If the page is cached or prerendered, nothing will be rendered until the user session is fetched on the client-side.
You can use the `placeholder` slot to show a placeholder on server-side and while the user session is being fetched on client-side for the prerendered pages:
```vue
Logout
Login
Loading...
```
If you are caching your routes with `routeRules`, please make sure to use [`nitro-nightly`](https://nitro.unjs.io/guide/nightly) or Nitro >= `2.10.0` to support the client-side fetching of the user session.
## Configuration
We leverage `runtimeConfig.session` to give the defaults option to [h3 `useSession`](https://h3.unjs.io/examples/handle-session).
You can overwrite the options in your `nuxt.config.ts`:
```ts
export default defineNuxtConfig({
modules: ['nuxt-auth-utils'],
runtimeConfig: {
session: {
maxAge: 60 * 60 * 24 * 7 // 1 week
}
}
})
```Our defaults are:
```ts
{
name: 'nuxt-session',
password: process.env.NUXT_SESSION_PASSWORD || '',
cookie: {
sameSite: 'lax'
}
}
```Checkout the [`SessionConfig`](https://github.com/unjs/h3/blob/c04c458810e34eb15c1647e1369e7d7ef19f567d/src/utils/session.ts#L20) for all options.
## More
- [nuxt-authorization](https://github.com/barbapapazes/nuxt-authorization): Authorization module for managing permissions inside a Nuxt app, compatible with `nuxt-auth-utils`
## Development
```bash
# Install dependencies
npm install# Generate type stubs
npm run dev:prepare# Develop with the playground
npm run dev# Build the playground
npm run dev:build# Run ESLint
npm run lint# Run Vitest
npm run test
npm run test:watch# Release new version
npm run release
```[npm-version-src]: https://img.shields.io/npm/v/nuxt-auth-utils/latest.svg?style=flat&colorA=020420&colorB=00DC82
[npm-version-href]: https://npmjs.com/package/nuxt-auth-utils[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-auth-utils.svg?style=flat&colorA=020420&colorB=00DC82
[npm-downloads-href]: https://npmjs.com/package/nuxt-auth-utils[license-src]: https://img.shields.io/npm/l/nuxt-auth-utils.svg?style=flat&colorA=020420&colorB=00DC82
[license-href]: https://npmjs.com/package/nuxt-auth-utils[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
[nuxt-href]: https://nuxt.com