curl -X GET "http://localhost:8080/user" \ -H "Authorization: Bearer your_access_token_here"
{ "id": "123e4567-e89b-12d3-a456-426614174000", "aud": "authenticated", "role": "authenticated", "email": "[email protected]", "email_confirmed_at": "2024-01-15T10:30:00Z", "phone": "+1234567890", "phone_confirmed_at": "2024-01-15T10:35:00Z", "confirmed_at": "2024-01-15T10:30:00Z", "last_sign_in_at": "2024-01-20T14:22:00Z", "app_metadata": { "provider": "email", "providers": ["email", "phone"] }, "user_metadata": { "first_name": "John", "last_name": "Doe", "avatar_url": "https://example.com/avatars/user123.jpg", "preferences": { "theme": "dark", "notifications": true } }, "identities": [ { "id": "123e4567-e89b-12d3-a456-426614174000", "user_id": "123e4567-e89b-12d3-a456-426614174000", "identity_data": { "email": "[email protected]", "sub": "123e4567-e89b-12d3-a456-426614174000" }, "provider": "email", "last_sign_in_at": "2024-01-20T14:22:00Z", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-20T14:22:00Z" } ], "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-20T14:22:00Z" }
Get authenticated user profile information
{ "code": 401, "msg": "Invalid token", "details": "The access token is invalid or expired" }
import { useState, useEffect } from 'react'; function UserProfile() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); useEffect(() => { fetchUserProfile(); }, []); const fetchUserProfile = async () => { try { const token = localStorage.getItem('access_token'); if (!token) { throw new Error('No access token found'); } const response = await fetch('/api/auth/user', { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, }); if (!response.ok) { if (response.status === 401) { // Token expired, redirect to login localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); window.location.href = '/login'; return; } throw new Error('Failed to fetch user profile'); } const userData = await response.json(); setUser(userData); } catch (err) { setError(err.message); } finally { setLoading(false); } }; if (loading) { return ( <div className="profile-loading"> <div className="spinner"></div> <p>Loading profile...</p> </div> ); } if (error) { return ( <div className="profile-error"> <p>Error: {error}</p> <button onClick={fetchUserProfile}>Retry</button> </div> ); } if (!user) { return <div>No user data available</div>; } return ( <div className="user-profile"> <div className="profile-header"> <div className="avatar"> {user.user_metadata?.avatar_url ? ( <img src={user.user_metadata.avatar_url} alt="Profile" className="avatar-image" /> ) : ( <div className="avatar-placeholder"> {user.user_metadata?.first_name?.[0] || user.email[0].toUpperCase()} </div> )} </div> <div className="profile-info"> <h1> {user.user_metadata?.first_name && user.user_metadata?.last_name ? `${user.user_metadata.first_name} ${user.user_metadata.last_name}` : user.email } </h1> <p className="email">{user.email}</p> {user.phone && ( <p className="phone">{user.phone}</p> )} </div> </div> <div className="profile-details"> <div className="detail-section"> <h3>Account Information</h3> <div className="detail-grid"> <div className="detail-item"> <label>User ID</label> <span className="user-id">{user.id}</span> </div> <div className="detail-item"> <label>Member Since</label> <span>{new Date(user.created_at).toLocaleDateString()}</span> </div> <div className="detail-item"> <label>Last Sign In</label> <span> {user.last_sign_in_at ? new Date(user.last_sign_in_at).toLocaleString() : 'Never' } </span> </div> <div className="detail-item"> <label>Account Status</label> <span className={`status ${user.confirmed_at ? 'confirmed' : 'pending'}`}> {user.confirmed_at ? 'Verified' : 'Pending Verification'} </span> </div> </div> </div> <div className="detail-section"> <h3>Verification Status</h3> <div className="verification-status"> <div className="verification-item"> <span className="verification-label">Email</span> <span className={`verification-badge ${user.email_confirmed_at ? 'verified' : 'unverified'}`}> {user.email_confirmed_at ? '✓ Verified' : '⚠ Unverified'} </span> </div> {user.phone && ( <div className="verification-item"> <span className="verification-label">Phone</span> <span className={`verification-badge ${user.phone_confirmed_at ? 'verified' : 'unverified'}`}> {user.phone_confirmed_at ? '✓ Verified' : '⚠ Unverified'} </span> </div> )} </div> </div> {user.identities && user.identities.length > 0 && ( <div className="detail-section"> <h3>Connected Accounts</h3> <div className="identities-list"> {user.identities.map((identity, index) => ( <div key={index} className="identity-item"> <span className="identity-provider">{identity.provider}</span> <span className="identity-date"> Connected {new Date(identity.created_at).toLocaleDateString()} </span> </div> ))} </div> </div> )} {user.user_metadata && Object.keys(user.user_metadata).length > 0 && ( <div className="detail-section"> <h3>Profile Data</h3> <div className="metadata-display"> {Object.entries(user.user_metadata).map(([key, value]) => ( <div key={key} className="metadata-item"> <label>{key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}</label> <span>{typeof value === 'object' ? JSON.stringify(value) : String(value)}</span> </div> ))} </div> </div> )} </div> <div className="profile-actions"> <button onClick={() => window.location.href = '/profile/edit'} className="edit-profile-btn" > Edit Profile </button> <button onClick={() => window.location.href = '/settings'} className="settings-btn" > Account Settings </button> </div> </div> ); } export default UserProfile;
import { useState, useEffect, useCallback } from 'react'; function useUser() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const fetchUser = useCallback(async () => { try { setLoading(true); setError(null); const token = localStorage.getItem('access_token'); if (!token) { throw new Error('No access token'); } const response = await fetch('/api/auth/user', { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, }); if (!response.ok) { if (response.status === 401) { // Clear tokens and redirect to login localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); window.location.href = '/login'; return; } throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const userData = await response.json(); setUser(userData); } catch (err) { setError(err.message); setUser(null); } finally { setLoading(false); } }, []); useEffect(() => { fetchUser(); }, [fetchUser]); const refreshUser = useCallback(() => { fetchUser(); }, [fetchUser]); return { user, loading, error, refreshUser, isAuthenticated: !!user, isEmailVerified: !!user?.email_confirmed_at, isPhoneVerified: !!user?.phone_confirmed_at, }; } export default useUser;
const express = require('express'); const { authenticateToken } = require('../middleware/auth'); const router = express.Router(); router.get('/user', authenticateToken, async (req, res) => { try { // The user ID is available from the JWT token via middleware const userId = req.user.sub; // Call Strike Auth Service to get user details const response = await fetch(`${process.env.AUTH_SERVICE_URL}/user`, { method: 'GET', headers: { 'Authorization': req.headers.authorization, 'Content-Type': 'application/json', }, }); if (!response.ok) { const errorData = await response.json(); return res.status(response.status).json(errorData); } const userData = await response.json(); // Log user profile access console.log(`User profile accessed: ${userData.id} (${userData.email})`); res.json(userData); } catch (error) { console.error('Get user profile error:', error); res.status(500).json({ code: 500, msg: 'Internal server error', details: 'Failed to retrieve user profile' }); } }); module.exports = router;
const jwt = require('jsonwebtoken'); function authenticateToken(req, res, next) { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN if (!token) { return res.status(401).json({ code: 401, msg: 'Access token required', details: 'Please provide a valid access token' }); } try { // Verify the JWT token const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (error) { if (error.name === 'TokenExpiredError') { return res.status(401).json({ code: 401, msg: 'Token expired', details: 'Please refresh your access token' }); } return res.status(403).json({ code: 403, msg: 'Invalid token', details: 'The provided token is invalid' }); } } module.exports = { authenticateToken };
{ "app_metadata": { "provider": "email", "providers": ["email", "phone", "google"], "roles": ["user"], "plan": "premium", "subscription_id": "sub_1234567890", "created_by": "admin", "internal_id": "INT_123456" } }
{ "user_metadata": { "first_name": "John", "last_name": "Doe", "avatar_url": "https://example.com/avatars/user123.jpg", "bio": "Software developer passionate about building great products", "website": "https://johndoe.dev", "location": "San Francisco, CA", "timezone": "America/Los_Angeles", "preferences": { "theme": "dark", "language": "en", "notifications": { "email": true, "push": false, "sms": true } }, "social_links": { "twitter": "@johndoe", "linkedin": "johndoe", "github": "johndoe" } } }
Frontend Implementation
Backend Implementation
Data Management
describe('GET /user', () => { test('should return user profile for authenticated user', async () => { const token = await getValidAccessToken(); const response = await request(app) .get('/user') .set('Authorization', `Bearer ${token}`) .expect(200); expect(response.body.id).toBeDefined(); expect(response.body.email).toBeDefined(); expect(response.body.created_at).toBeDefined(); }); test('should return 401 for missing token', async () => { await request(app) .get('/user') .expect(401); }); test('should return 401 for invalid token', async () => { await request(app) .get('/user') .set('Authorization', 'Bearer invalid_token') .expect(401); }); test('should return 401 for expired token', async () => { const expiredToken = generateExpiredToken(); await request(app) .get('/user') .set('Authorization', `Bearer ${expiredToken}`) .expect(401); }); });