AbsoluteJS
AbsoluteJS

Absolute Auth

A comprehensive TypeScript-based authentication system built for Elysia applications. Complete OAuth 2.0 solution with optional OpenID Connect capabilities and end-to-end type safety.

View on GitHub
#

Key Features

Multi-Provider Support

66 OAuth 2.0 providers with OpenID Connect support

Type-Safe

Full TypeScript support with comprehensive type definitions

Session Management

Built-in session handling with automatic expiration

Token Management

Automatic token refresh and revocation support

Route Protection

Easy-to-use route protection with typed callbacks

Event Hooks

Customizable handlers for all authentication flows

PKCE Support

Automatic PKCE implementation for supported providers

Security

Secure cookie handling and CSRF protection built-in

UserYour AppAbsoluteAuthProvider1. Login click2. /oauth2/auth/:provider3. State + PKCEgenerate4. Redirect5. User login(external)6. Callback + code7. Exchange code for token8. Session createdAbsoluteAuth handles steps 2-8 automatically
#

Installation

BASH
bun install @absolutejs/auth
#

Basic Setup

TS
1import { Elysia } from 'elysia';
2import { absoluteAuth } from '@absolutejs/auth';
3import { getEnv } from '@absolutejs/absolute';
4
5const app = new Elysia()
6  .use(absoluteAuth<User>({
7    providersConfiguration: {
8      google: {
9        credentials: {
10          clientId: getEnv('GOOGLE_CLIENT_ID'),
11          clientSecret: getEnv('GOOGLE_CLIENT_SECRET'),
12          redirectUri: 'http://localhost:3000/oauth2/callback'
13        },
14        scope: ['openid', 'profile', 'email']
15      }
16    }
17  }))
18  .listen(3000);
#

Protect Routes

The protectRoute helper function protects routes that require authentication. It accepts two callbacks with fully typed parameters - the user object matches your exact user shape, and the error object is one of the specific authentication errors, giving you complete type safety for both success and failure paths.

TS
1app.get('/protected', ({ status, protectRoute }) =>
2  protectRoute(
3    (user) => {
4      return `Hello, ${user.name}!`;
5    },
6    (error) => status(error.code, error.message)
7  )
8);
#

Handle Authentication Flow

When you use the Absolute Auth plugin, it automatically creates all the authentication routes you need. You do not implement your own login, status, or sign-out routes, you simply call the ones already provided.

Start the OAuth flow

TS
1// Option 1: Use an anchor element
2<a href="/oauth2/google/authorization">Sign in with Google</a>
3
4// Option 2: Redirect the user to the provider's authorization URL
5redirect('/oauth2/google/authorization');

This triggers the built-in authorization route, which handles:

  • Generating state + PKCE (if required)
  • Storing the provider name
  • Storing the origin URL
  • Building and redirecting to the provider's authorization URL

Check whether the user is logged in

TS
1import { server } from '/src/frontend/utils/edenTreaty';
2
3const { data, error } = await server.oauth2.status.get();
4
5if (error) {
6  console.error('Not authenticated:', error);
7} else {
8  console.log('User:', data.user);
9}

Sign the user out

TS
1import { server } from '/src/frontend/utils/edenTreaty';
2
3const { data, error } = await server.oauth2.signout.delete();
4
5if (error) {
6  console.error('Signout failed:', error);
7} else {
8  console.log('Successfully signed out');
9}

This calls the built-in sign-out route, which:

  • Runs your onSignOut hook (if provided)
  • Deletes the user session
  • Clears authentication cookies
#

Authentication Routes

The library automatically creates the following routes:

RouteMethodDescription
/oauth2/:provider/authorizationGETInitiate OAuth flow with specified provider
/oauth2/callbackGETHandle OAuth callback and token exchange
/oauth2/statusGETCheck current user authentication status
/oauth2/profileGETFetch user profile from OAuth provider
/oauth2/tokensPOSTRefresh access token using refresh token
/oauth2/revocationPOSTRevoke access or refresh token
/oauth2/signoutDELETESign out user and clear session
#

Session Management

Absolute Auth provides automatic session management with configurable lifetimes and cleanup. Sessions are automatically cleaned up at regular intervals, and you can also trigger cleanup manually using the derived cleanupSessions function.

Configuration

Configure session behavior using millisecond-based options:

TS
1.use(await absoluteAuth<User>({
2  providersConfiguration: { /* ... */ },
3
4  // Session lifetime configuration
5  sessionDurationMs: 86400000,            // 24 hours (default)
6  unregisteredSessionDurationMs: 3600000, // 1 hour (default)
7  cleanupIntervalMs: 300000,              // 5 minutes (default)
8  maxSessions: 5,                         // Max sessions per user (default)
9
10  // Called when sessions are cleaned up
11  onSessionCleanup: async ({ removedSessions, removedUnregisteredSessions }) => {
12    console.log(`Cleaned up ${removedSessions.size} expired sessions`);
13  }
14}))

The cleanup process:

  • Runs automatically at the interval specified by cleanupIntervalMs
  • Removes sessions older than sessionDurationMs
  • Removes unregistered sessions older than unregisteredSessionDurationMs
  • Enforces the maxSessions limit per user, removing oldest sessions first
  • Calls the onSessionCleanup hook with maps of removed sessions

The cleanupSessions Derived Function

When you use absoluteAuth, a cleanupSessions function is derived and made available in all your route handlers. This allows you to trigger cleanup programmatically:

TS
1// The cleanupSessions function is derived from the auth middleware
2// and available in all route handlers
3
4app.post('/admin/cleanup', async ({ cleanupSessions }) => {
5  // Manually trigger session cleanup
6  await cleanupSessions();
7  return { message: 'Sessions cleaned up' };
8});
9
10// You can also use it in scheduled tasks
11app.get('/health', async ({ cleanupSessions }) => {
12  // Cleanup runs automatically via cleanupIntervalMs,
13  // but can be triggered manually if needed
14  await cleanupSessions();
15  return { status: 'healthy' };
16})

The derived function follows Elysia's plugin pattern - it captures the session configuration from when absoluteAuth was initialized and provides a simple async function you can call from any route.

#

Custom User Handling

Absolute Auth does not provide database adapters. Instead, it exposes hooks throughout the OAuth lifecycle, allowing you to integrate any persistence layer or user model. These hooks provide full control over user creation, updates, and session handling while keeping the OAuth flow standardized and database-agnostic.

Core Hook: onCallbackSuccess

Called after the provider returns and tokens are exchanged. Use it to load or create users via instantiateUserSession:

TS
1onCallbackSuccess: async ({ authProvider, tokenResponse, session, userSessionId }) =>
2  instantiateUserSession({
3    authProvider,
4    tokenResponse,
5    session,
6    userSessionId,
7    getUser: async (userIdentity) => {
8      // Find user in your database
9      return await db.users.findByAuthSub(userIdentity.sub);
10    },
11    onNewUser: async (userIdentity) => {
12      // Create new user in your database
13      return await db.users.create({
14        authSub: userIdentity.sub,
15        email: userIdentity.email,
16        name: userIdentity.name
17      });
18    }
19  })

Route Configuration Props

Customize the route paths for all authentication endpoints:

PropDefaultDescription
authorizeRoute/oauth2/:provider/authorizationCustom authorization route path
callbackRoute/oauth2/callbackCustom callback route path
statusRoute/oauth2/statusCustom status check route path
signoutRoute/oauth2/signoutCustom sign-out route path
profileRoute/oauth2/profileCustom profile fetch route path
refreshRoute/oauth2/tokensCustom token refresh route path
revokeRoute/oauth2/revocationCustom token revocation route path

Lifecycle Hooks

Hook into each stage of the OAuth flow for custom behavior:

HookDescription
onAuthorizeSuccessCalled before redirecting to provider
onAuthorizeErrorCalled when authorization URL generation fails
onCallbackSuccessCalled after successful token exchange
onCallbackErrorCalled when callback/token exchange fails
onProfileSuccessCalled after successful profile fetch
onProfileErrorCalled when profile fetch fails
onStatusCalled when checking user session status
onRefreshSuccessCalled after successful token refresh
onRefreshErrorCalled when token refresh fails
onRevocationSuccessCalled after successful token revocation
onRevocationErrorCalled when token revocation fails
onSignOutCalled before session destruction
onSessionCleanupCalled when expired sessions are removed during cleanup