User Details in ID Token
The User Details in ID Token setting determines whether Personally Identifiable Information (PII)—such as the user's email, profile picture, and name—is returned in the JWT identity token issued by Web3Auth. This configuration allows you to control the level of user information available directly within the authentication token.

User Data Overview
JWT identity tokens can include various types of user information, ranging from minimal identifiers to comprehensive profile data. The configuration of this setting impacts both functionality and privacy considerations for your application.
Available User Data Types
Basic Identifier Information:
- User ID (always included)
 - Wallet address (always included)
 - Authentication timestamp (always included)
 
Optional Profile Information:
- Email address
 - Full name
 - Profile picture URL
 - Social login provider data
 - Custom user metadata
 
Configuration Options
Enable User Data in Tokens
When enabled, the identity token includes comprehensive user profile information:
{
  "iss": "https://api.web3auth.io",
  "sub": "user_unique_identifier",
  "aud": "your_client_id",
  "exp": 1640995200,
  "iat": 1640908800,
  "email": "user@example.com",
  "name": "John Doe",
  "picture": "https://profile-pics.com/user.jpg",
  "provider": "google",
  "wallet_address": "0x1234567890abcdef...",
  "custom_data": {
    "user_tier": "premium",
    "registration_date": "2023-01-15"
  }
}
Disable User Data in Tokens
When disabled, the identity token contains only essential identification information:
{
  "iss": "https://api.web3auth.io",
  "sub": "user_unique_identifier",
  "aud": "your_client_id",
  "exp": 1640995200,
  "iat": 1640908800,
  "wallet_address": "0x1234567890abcdef..."
}
Email-Only Mode
When userIdentifier is set to email, only the user's email is included in the token:
{
  "iss": "https://api.web3auth.io",
  "sub": "user_unique_identifier",
  "aud": "your_client_id",
  "exp": 1640995200,
  "iat": 1640908800,
  "email": "user@example.com",
  "wallet_address": "0x1234567890abcdef..."
}
Implementation Patterns
Token Parsing and Validation
Complete Token Processing:
import jwt from 'jsonwebtoken'
async function processUserToken(idToken) {
  try {
    // Verify and decode the token
    const decoded = jwt.verify(idToken, publicKey, {
      issuer: 'https://api.web3auth.io',
      audience: 'your_client_id',
    })
    // Extract user information
    const userProfile = {
      id: decoded.sub,
      walletAddress: decoded.wallet_address,
      email: decoded.email || null,
      name: decoded.name || null,
      picture: decoded.picture || null,
      provider: decoded.provider || null,
      customData: decoded.custom_data || {},
    }
    return userProfile
  } catch (error) {
    console.error('Token validation failed:', error)
    throw new Error('Invalid user token')
  }
}
Conditional Data Handling:
function extractUserData(decodedToken) {
  const baseData = {
    userId: decodedToken.sub,
    walletAddress: decodedToken.wallet_address,
    issuedAt: new Date(decodedToken.iat * 1000),
    expiresAt: new Date(decodedToken.exp * 1000),
  }
  // Handle optional profile data
  if (decodedToken.email) {
    baseData.email = decodedToken.email
  }
  if (decodedToken.name) {
    baseData.displayName = decodedToken.name
  }
  if (decodedToken.picture) {
    baseData.profilePicture = decodedToken.picture
  }
  if (decodedToken.custom_data) {
    baseData.metadata = decodedToken.custom_data
  }
  return baseData
}
Frontend Integration
React Implementation:
import { useEffect, useState } from 'react'
import { Web3Auth } from '@web3auth/modal'
function UserProfile() {
  const [userInfo, setUserInfo] = useState(null)
  useEffect(() => {
    const loadUserData = async () => {
      if (web3auth.status === 'connected') {
        // Get ID token with user data
        const idToken = await web3auth.authenticateUser()
        // Parse user information from token
        const userProfile = parseUserToken(idToken.idToken)
        setUserInfo(userProfile)
      }
    }
    loadUserData()
  }, [])
  if (!userInfo) {
    return <div>Loading user profile...</div>
  }
  return (
    <div className="user-profile">
      {userInfo.picture && <img src={userInfo.picture} alt="Profile" />}
      {userInfo.name && <h2>{userInfo.name}</h2>}
      {userInfo.email && <p>Email: {userInfo.email}</p>}
      <p>Wallet: {userInfo.walletAddress}</p>
    </div>
  )
}
Vue Implementation:
<template>
  <div class="user-profile" v-if="userInfo">
    <img v-if="userInfo.picture" :src="userInfo.picture" alt="Profile" />
    <h2 v-if="userInfo.name">{{ userInfo.name }}</h2>
    <p v-if="userInfo.email">Email: {{ userInfo.email }}</p>
    <p>Wallet: {{ userInfo.walletAddress }}</p>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        userInfo: null,
      }
    },
    async mounted() {
      if (this.$web3auth.status === 'connected') {
        const idToken = await this.$web3auth.authenticateUser()
        this.userInfo = this.parseUserToken(idToken.idToken)
      }
    },
    methods: {
      parseUserToken(token) {
        // Implementation to parse JWT token
        return parseUserToken(token)
      },
    },
  }
</script>
Use Cases and Benefits
Streamlined User Onboarding
Profile Pre-population:
async function setupUserAccount(idToken) {
  const userProfile = parseUserToken(idToken)
  // Pre-populate user profile from token data
  const accountData = {
    email: userProfile.email,
    displayName: userProfile.name,
    avatarUrl: userProfile.picture,
    authProvider: userProfile.provider,
    walletAddress: userProfile.walletAddress,
  }
  // Create user account with pre-filled information
  await createUserAccount(accountData)
  // Skip additional profile setup steps
  redirectToMainApplication()
}
Personalized User Experience
Dynamic UI Customization:
function personalizeInterface(userProfile) {
  // Customize greeting based on available name
  const greeting = userProfile.name ? `Welcome back, ${userProfile.name}!` : `Welcome back!`
  // Update profile avatar
  if (userProfile.picture) {
    updateUserAvatar(userProfile.picture)
  }
  // Apply user-specific settings
  if (userProfile.customData?.theme) {
    applyUserTheme(userProfile.customData.theme)
  }
  // Show personalized content
  displayPersonalizedContent(userProfile)
}
Session Management
Enhanced Session Context:
class SessionManager {
  constructor(idToken) {
    this.userProfile = parseUserToken(idToken)
    this.sessionData = this.initializeSession()
  }
  initializeSession() {
    return {
      userId: this.userProfile.id,
      email: this.userProfile.email,
      displayName: this.userProfile.name,
      walletAddress: this.userProfile.walletAddress,
      loginProvider: this.userProfile.provider,
      sessionStart: new Date(),
      lastActivity: new Date(),
    }
  }
  updateActivity() {
    this.sessionData.lastActivity = new Date()
    // Log activity with user context
    this.logUserActivity({
      userId: this.sessionData.userId,
      email: this.sessionData.email,
      action: 'page_view',
      timestamp: new Date(),
    })
  }
}
Privacy and Compliance Considerations
Data Minimization Principles
GDPR Compliance:
- Only include necessary user data in tokens
 - Obtain explicit consent for PII inclusion
 - Provide clear privacy notices
 - Enable data portability and deletion
 
Implementation Example:
class PrivacyCompliantTokenHandler {
  constructor(privacySettings) {
    this.allowedFields = privacySettings.allowedTokenFields
    this.userConsent = privacySettings.userConsent
  }
  processUserToken(rawToken) {
    const decodedToken = jwt.decode(rawToken)
    const filteredData = {}
    // Only include fields user consented to
    this.allowedFields.forEach(field => {
      if (decodedToken[field] && this.userConsent[field]) {
        filteredData[field] = decodedToken[field]
      }
    })
    return filteredData
  }
}
Regional Compliance
Multi-Jurisdictional Considerations:
function getRegionSpecificTokenHandling(userRegion) {
  const regionPolicies = {
    EU: {
      requireExplicitConsent: true,
      dataRetentionDays: 90,
      allowProfilePictures: false,
      requireDataProcessingNotice: true,
    },
    US: {
      requireExplicitConsent: false,
      dataRetentionDays: 365,
      allowProfilePictures: true,
      requireDataProcessingNotice: false,
    },
    APAC: {
      requireExplicitConsent: true,
      dataRetentionDays: 180,
      allowProfilePictures: true,
      requireDataProcessingNotice: true,
    },
  }
  return regionPolicies[userRegion] || regionPolicies['EU'] // Default to strictest
}
Security Considerations
Token Security Best Practices
Secure Token Handling:
class SecureTokenProcessor {
  constructor() {
    this.tokenCache = new Map()
    this.encryptionKey = process.env.TOKEN_ENCRYPTION_KEY
  }
  async processToken(idToken) {
    // Validate token signature
    const isValid = await this.validateTokenSignature(idToken)
    if (!isValid) {
      throw new Error('Invalid token signature')
    }
    // Check for token replay attacks
    if (this.isTokenReplayed(idToken)) {
      throw new Error('Token replay detected')
    }
    // Extract and sanitize user data
    const userData = this.extractUserData(idToken)
    return this.sanitizeUserData(userData)
  }
  sanitizeUserData(userData) {
    // Remove potentially dangerous content
    const sanitized = { ...userData }
    if (sanitized.name) {
      sanitized.name = this.sanitizeString(sanitized.name)
    }
    if (sanitized.email) {
      sanitized.email = this.validateEmail(sanitized.email)
    }
    if (sanitized.picture) {
      sanitized.picture = this.validateImageUrl(sanitized.picture)
    }
    return sanitized
  }
}
Data Validation
Input Validation and Sanitization:
function validateUserData(userData) {
  const validators = {
    email: email => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email),
    name: name => name.length <= 100 && !/[<>]/.test(name),
    picture: url => {
      try {
        const parsed = new URL(url)
        return ['https:'].includes(parsed.protocol)
      } catch {
        return false
      }
    },
  }
  const validatedData = {}
  Object.keys(userData).forEach(key => {
    if (validators[key]) {
      if (validators[key](userData[key])) {
        validatedData[key] = userData[key]
      } else {
        console.warn(`Invalid ${key} data:`, userData[key])
      }
    } else {
      validatedData[key] = userData[key]
    }
  })
  return validatedData
}
Performance Considerations
Token Size Management
Optimizing Token Size:
- Include only necessary user fields
 - Avoid large profile pictures (use URLs instead)
 - Limit custom metadata size
 - Consider token size impact on network performance
 
Token Size Monitoring:
function analyzeTokenSize(idToken) {
  const tokenSize = new Blob([idToken]).size
  const decoded = jwt.decode(idToken)
  const analysis = {
    totalSize: tokenSize,
    headerSize: JSON.stringify(decoded.header).length,
    payloadSize: JSON.stringify(decoded.payload).length,
    signatureSize: idToken.split('.')[2].length,
    userDataSize: JSON.stringify({
      email: decoded.email,
      name: decoded.name,
      picture: decoded.picture,
      custom_data: decoded.custom_data,
    }).length,
  }
  // Log warning for large tokens
  if (tokenSize > 8192) {
    // 8KB threshold
    console.warn('Large JWT token detected:', analysis)
  }
  return analysis
}
Caching Strategies
Efficient User Data Caching:
class UserDataCache {
  constructor() {
    this.cache = new Map()
    this.ttl = 5 * 60 * 1000 // 5 minutes
  }
  getUserData(userId, idToken) {
    const cached = this.cache.get(userId)
    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data
    }
    // Parse fresh token data
    const userData = parseUserToken(idToken)
    // Cache with timestamp
    this.cache.set(userId, {
      data: userData,
      timestamp: Date.now(),
    })
    return userData
  }
  invalidateUser(userId) {
    this.cache.delete(userId)
  }
  clearExpired() {
    const now = Date.now()
    for (const [userId, cached] of this.cache.entries()) {
      if (now - cached.timestamp >= this.ttl) {
        this.cache.delete(userId)
      }
    }
  }
}
Decision Framework
When to Enable User Data in Tokens
Recommended for:
- Applications requiring immediate user context
 - Single-page applications with limited backend calls
 - Personalization-heavy interfaces
 - Offline-capable applications
 
Consider enabling when:
- User onboarding needs profile pre-population
 - UI personalization improves user experience
 - Session management benefits from user context
 - Reduced API calls for user data improve performance
 
When to Disable User Data in Tokens
Recommended for:
- High-security applications
 - Compliance-heavy environments
 - Applications with separate user management systems
 - Minimal data exposure requirements
 
Consider disabling when:
- Privacy regulations are strict
 - Token size is a concern
 - User data is managed separately
 - Security requirements prefer minimal token content
 
Email-Only Configuration
Optimal for:
- Applications needing user identification only
 - Email-based user management systems
 - Privacy-focused applications
 - Minimal PII exposure scenarios
 
Next Steps
- Session Management - Configure session duration and behavior
 - Key Export Settings - Control private key export permissions
 - Project Settings - Configure basic project information