JWT Authentication
Detailed documentation on how JWT (JSON Web Token) authentication works in the Ever Gauzy platform.
How JWT Worksโ
Token Structureโ
A Gauzy JWT access token contains:
{
"id": "user-uuid",
"email": "user@example.com",
"tenantId": "tenant-uuid",
"employeeId": "employee-uuid",
"role": "ADMIN",
"iat": 1704067200,
"exp": 1704153600
}
Claimsโ
| Claim | Description |
|---|---|
id | User ID |
email | User email |
tenantId | User's tenant ID |
employeeId | Associated employee ID (if applicable) |
role | User's role name |
iat | Issued at (Unix timestamp) |
exp | Expiry (Unix timestamp) |
Configurationโ
Environment Variablesโ
# JWT secret for signing access tokens
JWT_SECRET=your-very-secure-secret-key
# Access token expiration in seconds (default: 24 hours)
JWT_TOKEN_EXPIRATION_TIME=86400
# Refresh token secret
JWT_REFRESH_TOKEN_SECRET=your-refresh-token-secret
# Refresh token expiration in seconds (default: 7 days)
JWT_REFRESH_TOKEN_EXPIRATION_TIME=604800
warning
Always use strong, unique secrets in production. Never commit secrets to version control.
Token Lifecycleโ
1. Obtain Tokensโ
# Login request
POST /api/auth/login
Content-Type: application/json
{
"email": "admin@ever.co",
"password": "admin"
}
Response:
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"user": { ... }
}
2. Use Access Tokenโ
Include the access token in Authorization header:
GET /api/employee
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
3. Refresh Tokenโ
When the access token expires, use the refresh token to get a new pair:
POST /api/auth/refresh-token
Content-Type: application/json
{
"refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}
Response:
{
"token": "new-access-token",
"refreshToken": "new-refresh-token"
}
4. Token Expiry Flowโ
Passport Strategyโ
The JWT strategy validates tokens on every authenticated request:
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly configService: ConfigService,
private readonly userService: UserService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: configService.get("JWT_SECRET"),
});
}
async validate(payload: JwtPayload): Promise<IUser> {
const { id, tenantId } = payload;
const user = await this.userService.findOneById(id);
if (!user) throw new UnauthorizedException();
return user;
}
}
Token Storageโ
Web Applicationโ
Tokens are stored in:
- Local Storage โ persists across browser sessions
- Session Storage โ cleared when browser is closed
Desktop Applicationโ
Tokens are stored using:
- Electron Store โ secure, encrypted local storage
- Keychain/Credential Manager โ OS-level secure storage
Best Practicesโ
| Approach | Security | UX |
|---|---|---|
| Local Storage | โ ๏ธ XSS vulnerable | โ Persistent sessions |
| Session Storage | โ Session-scoped | โ ๏ธ Lost on close |
| HTTP-Only Cookies | โ XSS protected | โ Automatic |
| Electron Store | โ Encrypted | โ Native |
Error Responsesโ
| Error | Status | Description |
|---|---|---|
| Missing token | 401 | No Authorization header |
| Invalid token | 401 | Token signature invalid |
| Expired token | 401 | Token past exp time |
| User not found | 401 | Token user deleted/disabled |
| Refresh token expired | 401 | Must re-authenticate |
Related Pagesโ
- Auth Overview โ authentication architecture
- Social Auth โ OAuth provider setup
- API Overview โ using tokens with the API