With Authgear SDK for NestJS, you can protect your NestJS resource server (API) with Authgear in just a few lines of code. It validates Authgear JWT access tokens offline using OIDC discovery and JWKS — no network round-trip to Authgear on every request — and provides a NestJS module, an auth guard, and decorators for reading the authenticated user.
Quick links — 📚 Documentation · 🏁 Getting Started · 🗺️ Roadmap · 🛠️ Troubleshooting · 👥 Contributing
Authgear is a highly adaptable identity-as-a-service (IDaaS) platform for web and mobile applications. Authgear makes user authentication easier and faster to implement by integrating it into various types of applications — from single-page web apps to mobile applications to API services.
- Zero-trust authentication architecture with OpenID Connect (OIDC) standard.
- Easy-to-use interfaces for user registration and login, including email, phone, username as login ID, and password, OTP, magic links, etc.
- Support for a wide range of identity providers, such as Google, Apple, and Azure Active Directory.
- Support for Passkeys, biometric login, and Multi-Factor Authentication (MFA) such as SMS/email-based verification and authenticator apps with TOTP.
This SDK focuses on the resource server side: verifying the JWT access tokens that Authgear issues, so your NestJS API can trust the caller's identity.
- NestJS >= 10 (works with NestJS 10 and 11)
- Node.js >= 18
- "Issue JWT as access token" enabled for your Authgear application — this SDK validates JWT access tokens offline and does not support opaque tokens.
npm install @authgear/nestjs joseIn the Authgear Portal, open your application's settings and enable "Issue JWT as access token". Without this, Authgear issues opaque access tokens, which this SDK cannot validate offline.
Register AuthgearModule.forRoot() in your root module. Setting global: true registers AuthgearAuthGuard as a global guard so every route is protected by default.
// app.module.ts
import { Module } from '@nestjs/common';
import { AuthgearModule } from '@authgear/nestjs';
@Module({
imports: [
AuthgearModule.forRoot({
endpoint: 'https://my-project.authgear.cloud',
global: true, // register AuthgearAuthGuard as a global guard
}),
],
})
export class AppModule {}Prefer to load configuration asynchronously (e.g. from ConfigService)? Use forRootAsync():
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AuthgearModule } from '@authgear/nestjs';
@Module({
imports: [
ConfigModule.forRoot(),
AuthgearModule.forRootAsync({
global: true,
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
endpoint: config.getOrThrow<string>('AUTHGEAR_ENDPOINT'),
clientID: config.get<string>('AUTHGEAR_CLIENT_ID'),
}),
}),
],
})
export class AppModule {}When you register the module with global: true, every route requires a valid Bearer token by default. Use the @Public() decorator to opt a handler out of authentication:
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { Public } from '@authgear/nestjs';
@Controller()
export class AppController {
@Public()
@Get('health')
health() {
return { ok: true };
}
}If you did not register the guard globally, protect individual routes (or controllers) with @UseGuards(AuthgearAuthGuard):
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthgearAuthGuard } from '@authgear/nestjs';
@Controller('me')
@UseGuards(AuthgearAuthGuard)
export class MeController {
@Get()
me() {
/* ... */
}
}Use the @CurrentUser() parameter decorator to read the verified token claims in a protected handler:
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { CurrentUser, AuthgearClaims } from '@authgear/nestjs';
@Controller()
export class AppController {
@Get('me')
me(@CurrentUser() user: AuthgearClaims) {
return {
userId: user.sub,
isVerified: user.isVerified,
};
}
}AuthgearClaims exposes the common claims (sub, iss, aud, clientID, isVerified, isAnonymous, canReauthenticate) plus the full decoded JWT payload as raw for any custom claims.
Callers must send the access token as a Bearer token:
Authorization: Bearer <jwt-access-token>
forRoot() and the object returned by the forRootAsync() factory accept the following options:
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
endpoint |
string |
✓ | — | Authgear project endpoint, e.g. https://my-project.authgear.cloud. Used for OIDC discovery and JWKS. |
clientID |
string |
— | If set, the verifier also asserts the token's client_id claim equals this value. |
|
global |
boolean |
false |
Register AuthgearAuthGuard as a global APP_GUARD so all routes are protected. (forRoot/forRootAsync option.) |
|
jwksCacheMaxAge |
number |
— | JWKS cache max age in milliseconds (passed through to jose). |
|
clockToleranceSeconds |
number |
0 |
Leeway in seconds applied to exp/iat checks. |
You can also inject AuthgearTokenService directly if you need to verify a token outside of the guard.
Planned, within the resource-server scope:
- RBAC —
@RequireRoles()/@RequirePermissions()from configurable claim paths. - Opaque token validation — optional online validation (introspection / UserInfo) for instant revocation.
- M2M tokens — first-class machine-to-machine token support.
- Step-up auth —
@RequireRecentAuth()based on theauth_timeclaim.
Out of scope: the login flow, session refresh/revoke, user management, and non-auth utilities (rate limiting, audit logging, caching).
Every request returns 401 Unauthorized.
- Confirm "Issue JWT as access token" is enabled for the application in the Authgear Portal. Opaque tokens cannot be validated offline and will be rejected.
- Make sure the client sends the token in the
Authorization: Bearer <token>header. - If you set
clientID, confirm the token'sclient_idclaim matches it. - If tokens are rejected due to clock skew between your server and Authgear, set
clockToleranceSecondsto a small value.
The application fails to start, or the first request errors with a discovery/JWKS error.
- Check that
endpointis the correct Authgear project endpoint and is reachable from your server. The SDK fetches the OIDC discovery document and JWKS from this endpoint.
Contributions — documentation, features, bug fixes, tests, or code reviews — are very much welcome.
git clone git@github.com:authgear/authgear-sdk-nestjs.git
cd authgear-sdk-nestjs
npm install
npm test
npm run buildA runnable NestJS app demonstrating the SDK lives in example/. The documentation site source lives in docs/ and is published to https://authgear.github.io/authgear-sdk-nestjs/.
To join the community, raise your hand on the Authgear Discord server or the GitHub discussions board.
Authgear is a highly adaptable identity-as-a-service (IDaaS) platform for web and mobile applications. To learn more, visit authgear.com.