JSON Web Tokens (JWT) provide a secure way to handle user authentication and session management in Wappi applications. JWTs are stateless, scalable, and perfect for modern API architectures.
Wappi uses JWT tokens for user authentication through a dedicated login endpoint:
Create a login endpoint that generates JWT tokens:
1// API/Core/Login/1.0.0/index.ts
2import jwt from 'jsonwebtoken'
3import bcrypt from 'bcrypt'
4
5interface Core_Login_1_0_0__Body {
6 email: string
7 password: string
8}
9
10export default async function CoreLogin(body: Core_Login_1_0_0__Body) {
11 try {
12 // Validate user credentials
13 const user = await validateUser(body.email, body.password)
14
15 if (!user) {
16 throw new Error('Invalid credentials')
17 }
18
19 // Generate JWT token
20 const token = jwt.sign(
21 {
22 userId: user.id,
23 email: user.email,
24 role: user.role
25 },
26 process.env.JWT_SECRET,
27 {
28 expiresIn: '24h',
29 issuer: 'wappi-api',
30 audience: 'wappi-client'
31 }
32 )
33
34 return {
35 success: true,
36 data: {
37 user: {
38 id: user.id,
39 email: user.email,
40 name: user.name,
41 role: user.role
42 },
43 token,
44 expiresIn: '24h'
45 }
46 }
47 } catch (error) {
48 throw new Error('Authentication failed')
49 }
50}
51
52async function validateUser(email: string, password: string) {
53 // Implement your user validation logic
54 const user = await getUserByEmail(email)
55
56 if (!user || !await bcrypt.compare(password, user.hashedPassword)) {
57 return null
58 }
59
60 return user
61}1# JWT Secret for token signing
2JWT_SECRET=your-super-secret-jwt-key-here
3
4# Token expiration settings
5JWT_EXPIRES_IN=24h
6JWT_REFRESH_EXPIRES_IN=7d
7
8# JWT issuer and audience
9JWT_ISSUER=wappi-api
10JWT_AUDIENCE=wappi-client1{
2 "authRotation": "0 0 * * *", // Daily token rotation
3 "apiKey": "your-api-key",
4 "domains": "yourdomain.com, app.yourdomain.com"
5}Protect endpoints by requiring JWT authentication:
1// API/User/GetProfile/1.0.0/index.ts
2interface User_GetProfile_1_0_0__Body {
3 // JWT auth data is automatically added to authenticated requests
4 auth: {
5 userId: string
6 email: string
7 role: string
8 }
9}
10
11export default async function GetUserProfile(body: User_GetProfile_1_0_0__Body) {
12 try {
13 // Access authenticated user data from body.auth
14 const userId = body.auth.userId
15
16 const userProfile = await getUserProfile(userId)
17
18 return {
19 success: true,
20 data: userProfile
21 }
22 } catch (error) {
23 throw new Error('Failed to get user profile')
24 }
25}1import { request } from 'wappi-fe'
2import { WAPPI_CONFIG } from './wappiConfig'
3
4// Login function
5export const login = async (email: string, password: string) => {
6 const response = await request(WAPPI_CONFIG, {
7 name: 'User Login',
8 query: 'Core_Login_1_0_0',
9 data: { email, password },
10 authRequired: false, // Login doesn't require existing auth
11 successCallback: (data) => {
12 // Store JWT token in localStorage
13 localStorage.setItem('wappiAuthToken', data.token)
14 localStorage.setItem('wappiUser', JSON.stringify(data.user))
15 },
16 errorCallback: (error) => {
17 console.error('Login failed:', error)
18 }
19 })
20
21 return response
22}1// Making authenticated requests
2export const getUserProfile = async () => {
3 return await request(WAPPI_CONFIG, {
4 name: 'Get User Profile',
5 query: 'User_GetProfile_1_0_0',
6 data: {},
7 authRequired: true, // Automatically includes JWT token
8 errorCallback: (error) => {
9 if (error.statusCode === 401) {
10 // Token expired or invalid - redirect to login
11 localStorage.removeItem('wappiAuthToken')
12 window.location.href = '/login'
13 }
14 }
15 })
16}Implement token refresh for seamless user experience:
1// API/Core/RefreshToken/1.0.0/index.ts
2interface Core_RefreshToken_1_0_0__Body {
3 refreshToken: string
4}
5
6export default async function RefreshToken(body: Core_RefreshToken_1_0_0__Body) {
7 try {
8 // Validate refresh token
9 const decoded = jwt.verify(body.refreshToken, process.env.JWT_REFRESH_SECRET)
10
11 // Generate new access token
12 const newToken = jwt.sign(
13 {
14 userId: decoded.userId,
15 email: decoded.email,
16 role: decoded.role
17 },
18 process.env.JWT_SECRET,
19 { expiresIn: '24h' }
20 )
21
22 return {
23 success: true,
24 data: {
25 token: newToken,
26 expiresIn: '24h'
27 }
28 }
29 } catch (error) {
30 throw new Error('Invalid refresh token')
31 }
32}Wappi automatically handles JWT validation for protected endpoints:
1// Automatic JWT validation middleware (built into Wappi)
2function validateJWT(token: string) {
3 try {
4 const decoded = jwt.verify(token, process.env.JWT_SECRET)
5
6 // Check token expiration
7 if (decoded.exp < Date.now() / 1000) {
8 throw new Error('Token expired')
9 }
10
11 return {
12 success: true,
13 user: decoded
14 }
15 } catch (error) {
16 return {
17 success: false,
18 error: error.message
19 }
20 }
21}1// Frontend logout function
2export const logout = () => {
3 // Remove tokens from storage
4 localStorage.removeItem('wappiAuthToken')
5 localStorage.removeItem('wappiRefreshToken')
6 localStorage.removeItem('wappiUser')
7
8 // Redirect to login page
9 window.location.href = '/login'
10}
11
12// Optional: Server-side token blacklisting
13// API/Core/Logout/1.0.0/index.ts
14export default async function Logout(body: Core_Logout_1_0_0__Body) {
15 try {
16 // Add token to blacklist (optional)
17 await blacklistToken(body.auth.token)
18
19 return {
20 success: true,
21 message: 'Logged out successfully'
22 }
23 } catch (error) {
24 throw new Error('Logout failed')
25 }
26}Handle JWT-related errors gracefully:
1// Common JWT error responses
2{
3 "success": false,
4 "message": "Token expired",
5 "statusCode": 401,
6 "code": "TOKEN_EXPIRED"
7}
8
9{
10 "success": false,
11 "message": "Invalid token",
12 "statusCode": 401,
13 "code": "INVALID_TOKEN"
14}
15
16{
17 "success": false,
18 "message": "Token required",
19 "statusCode": 401,
20 "code": "TOKEN_REQUIRED"
21}1// Test JWT authentication
2curl -X POST https://api.yourdomain.com/Core/Login/1.0.0 \
3 -H "Content-Type: application/json" \
4 -d '{
5 "email": "user@example.com",
6 "password": "password123"
7 }'
8
9// Use returned token for authenticated requests
10curl -X GET https://api.yourdomain.com/User/GetProfile/1.0.0 \
11 -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
12 -H "Content-Type: application/json"1// Implement role-based access in endpoints
2export default async function AdminOnlyEndpoint(body: Admin_ManageUsers_1_0_0__Body) {
3 // Check user role from JWT token
4 if (body.auth.role !== 'admin') {
5 throw new Error('Insufficient permissions')
6 }
7
8 // Admin-only logic here
9 return {
10 success: true,
11 data: await getAdminData()
12 }
13}1// Add custom claims to JWT tokens
2const token = jwt.sign(
3 {
4 userId: user.id,
5 email: user.email,
6 role: user.role,
7 permissions: user.permissions,
8 organizationId: user.organizationId,
9 lastLogin: new Date().toISOString()
10 },
11 process.env.JWT_SECRET,
12 { expiresIn: '24h' }
13)