انتقل إلى المحتوى الرئيسي

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