Client Secrets

Client secrets are secure, session-specific tokens that allow your frontend applications to interact with FaceSign's verification interface. Unlike your API key, client secrets are safe to use in client-side code and are automatically included when you create or retrieve a session.

How client secrets work

Client secrets provide a secure way to authenticate frontend requests:

  1. Server-side session creation - Use your API key to create a session
  2. Client secret returned - FaceSign returns a session-specific client secret
  3. Frontend integration - Pass the client secret to your frontend or mobile app
  4. Secure verification - Frontend uses the client secret to access the verification interface
  5. Automatic expiration - Client secrets expire after 1 hour for security

Client secret properties

  • Name
    secret
    Type
    string
    Description

    The client secret token to use in frontend integrations.

  • Name
    createdAt
    Type
    number
    Description

    Unix timestamp when the client secret was created.

  • Name
    expireAt
    Type
    number
    Description

    Unix timestamp when the client secret expires (1 hour from creation).

  • Name
    url
    Type
    string
    Description

    Pre-built URL for hosted verification flow including the client secret.


Using client secrets

Web integration

For web applications, you can either redirect users to the hosted flow or use the JavaScript SDK:

Web integration

<!-- Server-side: Get client secret -->
<script>
  // Pass client secret from your server
  const clientSecret = "{{ clientSecret }}"; // From your backend
  const verificationUrl = `https://verify.facesign.ai/?client_secret=${clientSecret}`;
  
  // Redirect user to verification
  window.location.href = verificationUrl;
</script>

Mobile integration

For mobile applications, use the native SDKs:

Mobile integration

import FaceSignSDK

class VerificationViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        startVerification()
    }
    
    func startVerification() {
        // Get client secret from your backend
        getClientSecret { [weak self] clientSecret in
            DispatchQueue.main.async {
                let config = FaceSignConfig(
                    clientSecret: clientSecret,
                    delegate: self
                )
                
                let verificationVC = FaceSignViewController(config: config)
                self?.present(verificationVC, animated: true)
            }
        }
    }
    
    func getClientSecret(completion: @escaping (String) -> Void) {
        // Call your backend API to get client secret
        APIClient.createSession { result in
            switch result {
            case .success(let response):
                completion(response.clientSecret)
            case .failure(let error):
                print("Failed to get client secret: \(error)")
            }
        }
    }
}

extension VerificationViewController: FaceSignDelegate {
    func verificationCompleted(session: FaceSignSession) {
        if session.report.isVerified {
            // Verification successful
            navigateToDashboard()
        } else {
            // Verification failed
            showErrorAlert("Verification failed")
        }
    }
    
    func verificationCancelled() {
        // User cancelled verification
        dismiss(animated: true)
    }
}

Security considerations

Client secrets are safe for frontend use

Unlike API keys, client secrets are designed to be safe for client-side use:

  • Session-specific - Each client secret is tied to a single session
  • Time-limited - Automatically expire after 1 hour
  • Read-only - Cannot be used to create new sessions or access other data
  • Domain-restricted - Can be restricted to specific domains (contact support)

Best practices

  1. Fetch on demand - Get client secrets from your backend when needed
  2. Handle expiration - Refresh client secrets if they expire during verification
  3. Secure transmission - Always use HTTPS when transmitting client secrets
  4. Don't store long-term - Client secrets are meant for immediate use

Secure implementation

// Secure endpoint to create sessions
app.post('/api/create-verification', authenticate, async (req, res) => {
  // Verify user is authenticated
  if (!req.user) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  try {
    const { session, clientSecret } = await facesignClient.sessions.create({
      clientReferenceId: req.user.id,
      metadata: {
        userId: req.user.id,
        email: req.user.email,
        ipAddress: req.ip
      },
      modules: [{ type: 'identityVerification' }]
    });
    
    // Store session in your database
    await db.verifications.create({
      sessionId: session.id,
      userId: req.user.id,
      status: session.status,
      createdAt: new Date()
    });
    
    // Return only the client secret to frontend
    res.json({
      clientSecret: clientSecret.secret,
      sessionId: session.id
    });
    
  } catch (error) {
    console.error('Session creation failed:', error);
    res.status(500).json({ error: 'Failed to create verification session' });
  }
});

Handling expiration

Client secrets expire after 1 hour. If verification takes longer or you need to restart the process:

Handle expiration

async function handleClientSecretExpiration(sessionId: string) {
  try {
    // Call your backend to refresh the client secret
    const response = await fetch(`/api/refresh-verification/${sessionId}`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${userToken}`,
      }
    });
    
    const { clientSecret } = await response.json();
    
    // Reinitialize FaceSign with new client secret
    const facesign = new FaceSign({
      clientSecret: clientSecret
    });
    
    await facesign.mount('#verification-container');
    
  } catch (error) {
    console.error('Failed to refresh client secret:', error);
    // Redirect to start a new verification session
    window.location.href = '/start-verification';
  }
}

// Backend endpoint for refreshing
app.post('/api/refresh-verification/:sessionId', authenticate, async (req, res) => {
  const { sessionId } = req.params;
  
  // Verify the session belongs to the authenticated user
  const verification = await db.verifications.findFirst({
    where: { sessionId, userId: req.user.id }
  });
  
  if (!verification) {
    return res.status(404).json({ error: 'Session not found' });
  }
  
  try {
    const { clientSecret } = await facesignClient.sessions.refreshSecret(sessionId);
    
    res.json({
      clientSecret: clientSecret.secret
    });
    
  } catch (error) {
    console.error('Failed to refresh client secret:', error);
    res.status(500).json({ error: 'Failed to refresh client secret' });
  }
});

Next steps

  • Sessions - Learn about the session lifecycle
  • Webhooks - Get real-time updates about verification progress
  • Modules - Configure verification modules for your use case