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