Examples
Here are some common usage examples for elysia-auth.
Basic Authentication
import { Elysia } from 'elysia'
import { ElysiaAuth, authGuard } from 'elysia-auth'
import Google from '@auth/core/providers/google'
const app = new Elysia()
.use(ElysiaAuth({
providers: [
Google({
clientId: process.env.AUTH_GOOGLE_ID,
clientSecret: process.env.AUTH_GOOGLE_SECRET
})
],
secret: process.env.AUTH_SECRET
}))
.get('/', () => 'Welcome to the home page')
.group('/admin', app => app
.use(authGuard())
.get('/dashboard', () => 'Admin Dashboard')
)
.listen(3000)
Multi-Provider Setup
import { Elysia } from 'elysia'
import { ElysiaAuth } from 'elysia-auth'
import Google from '@auth/core/providers/google'
import GitHub from '@auth/core/providers/github'
import Credentials from '@auth/core/providers/credentials'
const app = new Elysia()
.use(ElysiaAuth({
providers: [
Google({
clientId: process.env.AUTH_GOOGLE_ID,
clientSecret: process.env.AUTH_GOOGLE_SECRET
}),
GitHub({
clientId: process.env.AUTH_GITHUB_ID,
clientSecret: process.env.AUTH_GITHUB_SECRET
}),
Credentials({
credentials: {
email: { type: "email" },
password: { type: "password" }
},
async authorize(credentials) {
const user = await db.user.findUnique({
where: { email: credentials.email }
})
if (user && verifyPassword(credentials.password, user.password)) {
return user
}
return null
}
})
],
secret: process.env.AUTH_SECRET
}))
Role-Based Access Control
import { Elysia } from 'elysia'
import { authGuard } from 'elysia-auth'
// Define custom user type with roles
type User = {
id: string
email: string
role: 'admin' | 'user'
}
const app = new Elysia()
.use(authGuard<User>({
getUserData: async (authUser) => {
const user = await db.user.findUnique({
where: { id: authUser.sub }
})
return {
id: user.id,
email: user.email,
role: user.role
}
}
}))
.get('/admin', ({ session }) => {
if (session.user.role !== 'admin') {
throw new Error('Admin access required')
}
return 'Admin Panel'
})
API Routes with Authentication
Either pass paths you want to protect in protectPaths(["/api","/api2"])
this will be added 1 time before routes
import { Elysia } from 'elysia'
import { protectPaths } from 'elysia-auth'
const app = new Elysia()
.use(protectPaths(['/api']))
.group('/api', app => app
.get('/users', async () => {
const users = await db.user.findMany()
return users
})
.post('/users', async ({ body }) => {
const user = await db.user.create({
data: body
})
return user
})
)
Or you can use authGaurd()
it will protect all routes this is under this middleware. this is scoped based, means it will only valid for single Elysia
instance means in the below example, this is only applied to postsModule
import { Elysia } from 'elysia'
import { authGaurd } from 'elysia-auth'
const postsModule = new Elysia()
.use(authGaurd())
.get('/users', async () => {
const users = await db.user.findMany()
return users
})
.post('/users', async ({ body }) => {
const user = await db.user.create({
data: body
})
return user
})
Session
After adding protectPaths
or authGaurd
there will be session
object in Elysia
Context
const postModules = new Elysia().use(authGuard()).get("/secret-api", (ctx) => {
const { user, isAuthenticated, authUser } = ctx.session;
return {
user,
isAuthenticated,
authUser,
};
});
Frontend Integration
For frontend you can either use template engine, means frontend is also on Elysia
app. In that case you can simply go to /auth/signin
for prebuild sign in form.
But in case of different client and server
You have to use form with post method and action will be ${backend_url}/auth/signin/github
in case of github, github will be changed respectivly to outh, in case of credentials action will be ${backend_url}/auth/callback/credentials
You can use the following REST API endpoints from your client-side code. NB: Make sure to include the csrfToken in the request body for all sign-in and sign-out requests.
if you don’t want to manually hit endpoint then you can use @auth/react
. It provides built-in handlers for credentials signin and oauth signin.
signInCredentials
for credentials signin - it takes email, password, redirect urlsignInOAuth
for oauth signin - it takes provider and redirect urlsignOut
for signout - it takes redirect url
More details on @auth/react
docs
If you different frontend then make sure to add these options in AuthOptions in ElysiaAuth()
It is so that after authentication user redirect back to frontend
// add redirect in callback, where the baseUrl will be backend url and url will be the callbackUrl (in this case it should be frontend Url)
callbacks: {
redirect: async ({ baseUrl, url }) => {
if (url.startsWith("http")) return url;
// Allows relative callback URLs
if (url.startsWith("/")) return `${baseUrl}${url}`;
// Allows callback URLs on the same origin
if (new URL(url).origin === baseUrl) return url;
return baseUrl;
},
},
// add custom signin & error page redirecting frontend
pages: {
signIn: "http://localhost:5173/signin",
error: "http://localhost:5173?error=Auth+Error",
},
Custom Error Handling
import { Elysia } from 'elysia'
import { authGuard } from 'elysia-auth'
const app = new Elysia()
.use(authGuard({
unauthorizedStatus: 403,
onFailure: (set) => {
set.status = 403
return {
error: 'Authentication required',
code: 'AUTH_REQUIRED',
redirect: '/auth/signin'
}
}
}))
WebSocket Authentication
import { Elysia } from 'elysia'
import { authGuard } from 'elysia-auth'
const app = new Elysia()
.ws('/chat', {
beforeHandle: ({ session }) => {
if (!session.isAuthenticated) {
throw new Error('Authentication required')
}
},
message: ({ data, session }) => {
return {
message: data,
user: session.user.email
}
}
})
Next Steps
- Check the API Reference for detailed documentation
- Learn about Security Best Practices
- Join our Discord Community