Skip to main content

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 Details Settings

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