Ga naar hoofdinhoud

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​

ClaimDescription
idUser ID
emailUser email
tenantIdUser's tenant ID
employeeIdAssociated employee ID (if applicable)
roleUser's role name
iatIssued at (Unix timestamp)
expExpiry (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​

ApproachSecurityUX
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​

ErrorStatusDescription
Missing token401No Authorization header
Invalid token401Token signature invalid
Expired token401Token past exp time
User not found401Token user deleted/disabled
Refresh token expired401Must re-authenticate