DEVOTP Documentation

Introduction

The DEVOTP User Verification system provides a secure, easy-to-implement solution for verifying user emails and phone numbers. This documentation will guide you through the integration process step by step.

Key Features

  • Email and SMS verification methods
  • Secure OTP generation and validation
  • Customizable UI with dark mode support
  • Comprehensive event handling
  • Server-side signature validation

Installation

Add the DEVOTP SDK to your project using CDN:

Using CDN

<script src="https://cdn.jsdelivr.net/npm/devotp-sdk@1.0.6/dist/devotp-sdk.bundle.js"></script>

Server-Side Package

For validating verification signatures on your server:

npm install user-verification-signature-decryptor

Quick Start

Follow these steps to integrate user verification into your application:

1. Create an Account

Follow these steps to set up your verification service:

  1. Create an account at https://devotp.com
  2. Start a subscription plan that fits your verification needs
  3. Create a site for which you wish to configure the product for verification of users
  4. Navigate to `Sites` and click on your site for details
  5. Click on the `Configure Theme` button
  6. Customize the UI for the verification button and modal to match your site`s color palette and design
  7. After configuration, obtain your Site ID and Client Key from the site details page

2. Add Client-Side Code

<!-- Email verification example -->
<div id="email-verification"></div>

<script src="https://cdn.jsdelivr.net/npm/devotp-sdk@1.0.6/dist/devotp-sdk.bundle.js"></script>
<script>
    let emailData = null;

    window.Devotp.initEmailVerification("#email-verification", {
        siteId: "YOUR_SITE_ID", // Replace with your actual site ID
        onSuccess: (data) => {
            console.log("Email verification successful:", data);
            emailData = data; // Store verification data
            
            // Access verified email and signature
            console.log("Email:", data.identifier);
            console.log("Signature:", data.signature);
            
            // Send to your server for validation
            fetch('/api/verify', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ 
                    email: data.identifier, 
                    signature: data.signature 
                })
            });
        },
        onError: (error) => {
            console.error("Email verification error:", error);
        }
    });
</script>

3. Implement Server-Side Validation

// Install the package
npm install user-verification-signature-decryptor

// In your server code (e.g., Express.js route)
const { PayloadDecryptor } = require('user-verification-signature-decryptor');

app.post('/api/verify', async (req, res) => {
    const { email, signature } = req.body;
    
    try {
        // Create decryptor with your Client Key
        const decryptor = new PayloadDecryptor('YOUR_CLIENT_KEY_HERE');
        
        // Validate the signature (handle both sync and async)
        const result = decryptor.validateDecryption(email, signature);
        const validationResult = typeof result.then === 'function' 
            ? await result 
            : result;
        
        if (validationResult.isValid) {
            // Mark user as verified in your database
            return res.json({ success: true });
        } else {
            return res.status(400).json({ 
                success: false, 
                error: 'Invalid signature' 
            });
        }
    } catch (error) {
        return res.status(500).json({ 
            success: false, 
            error: error.message 
        });
    }
});

Important Notes

  • Always replace YOUR_SITE_ID and YOUR_CLIENT_KEY_HERE with your actual credentials from the dashboard.
  • Store your Client Key securely as an environment variable, never hardcode it in your application.
  • Always validate signatures on your server side. Client-side verification alone is not secure.

Email Verification

To implement email verification, add the following HTML markup and JavaScript to your page:

<div id="email-verification"></div>

<!-- Load the DEVOTP SDK -->
<script src="https://cdn.jsdelivr.net/npm/devotp-sdk@1.0.6/dist/devotp-sdk.bundle.js"></script>

<script>
    window.Devotp.initEmailVerification("#email-verification", {
        siteId: "YOUR_SITE_ID", // Replace with your actual site ID
        onSuccess: (data) => {
            console.log("Email verification successful:", data);
            // data.identifier contains the verified email
            // data.signature contains the encrypted signature
        },
        onError: (error) => {
            console.error("Email verification error:", error);
        }
    });
</script>

Phone Verification

For phone verification, use this implementation:

<div id="phone-verification"></div>

<!-- Load the DEVOTP SDK -->
<script src="https://cdn.jsdelivr.net/npm/devotp-sdk@1.0.6/dist/devotp-sdk.bundle.js"></script>

<script>
    window.Devotp.initPhoneVerification("#phone-verification", {
        siteId: "YOUR_SITE_ID", // Replace with your actual site ID
        onSuccess: (data) => {
            console.log("Phone verification successful:", data);
            // data.identifier contains the verified phone number
            // data.signature contains the encrypted signature
        },
        onError: (error) => {
            console.error("Phone verification error:", error);
        }
    });
</script>

Configuration Options

Both initEmailVerification and initPhoneVerification accept the following configuration options:

window.Devotp.initEmailVerification("#email-verification", {
    siteId: "YOUR_SITE_ID",        // Required: Your site ID
    onSuccess: (data) => {         // Required: Success callback
        // Handle successful verification
        console.log(data.identifier); // Verified email/phone
        console.log(data.signature);  // Encrypted signature
    },
    onError: (error) => {          // Required: Error callback
        // Handle verification errors
        console.error(error);
    }
});

Event Handling

The DEVOTP SDK provides callback functions for handling verification events:

window.Devotp.initEmailVerification("#email-verification", {
    siteId: "YOUR_SITE_ID",
    onSuccess: (data) => {
        // Called when verification is successful
        console.log("Verification successful!");
        console.log("Verified identifier:", data.identifier);
        console.log("Signature for server validation:", data.signature);
        
        // Send to server for final validation
        validateOnServer(data.identifier, data.signature);
    },
    onError: (error) => {
        // Called when verification fails
        console.error("Verification failed:", error);
        
        // Show user-friendly error message
        showErrorMessage("Verification failed. Please try again.");
    }
});

function validateOnServer(identifier, signature) {
    fetch('/api/verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ identifier, signature })
    })
    .then(response => response.json())
    .then(result => {
        if (result.success) {
            console.log("Server validation successful!");
        }
    });
}

Signature Validation

After successful client-side verification, you will receive an encrypted signature that must be validated on your server:

const { PayloadDecryptor } = require('user-verification-signature-decryptor');

/**
 * Validate an OTP signature using the decryption library
 * 
 * @param {string} clientKey - Decryption key from site details
 * @param {string} identifier - Email or phone used for verification
 * @param {string} signature - Encrypted signature received
 * @returns {Promise<object>} Decryption result
 */
async function validateOtpSignature(clientKey, identifier, signature) {
    try {
        // Create decryptor instance
        const decryptor = new PayloadDecryptor(clientKey);

        // Validate the decryption (handle both sync and async)
        const result = decryptor.validateDecryption(identifier, signature);
        
        // Check if result is a Promise
        const validationResult = typeof result.then === 'function' 
            ? await result 
            : result;
        
        if (validationResult.isValid) {
            return {
                success: true,
                isValid: true,
                data: validationResult.decryptedData
            };
        } else {
            return {
                success: false,
                isValid: false,
                error: 'Invalid signature'
            };
        }
    } catch (error) {
        return {
            success: false,
            isValid: false,
            error: error.message
        };
    }
}

// Example usage
const clientKey = 'YOUR_CLIENT_DECRYPTION_KEY';
const email = 'user@example.com';
const signature = 'encrypted_signature_from_frontend';

const result = await validateOtpSignature(clientKey, email, signature);
console.log(result);

Express.js Example

Here is how to implement the verification in an Express.js application:

const express = require('express');
const { PayloadDecryptor } = require('user-verification-signature-decryptor');
const app = express();

app.use(express.json());

// Your decryption key from site details
const CLIENT_KEY = process.env.DEVOTP_CLIENT_KEY;

app.post('/api/submit-form', async (req, res) => {
    const { email, phone, email_signature, phone_signature } = req.body;
    
    try {
        let emailValidation = null;
        let phoneValidation = null;
        
        // Validate email if provided
        if (email && email_signature) {
            const decryptor = new PayloadDecryptor(CLIENT_KEY);
            const result = decryptor.validateDecryption(email, email_signature);
            emailValidation = typeof result.then === 'function' ? await result : result;
        }
        
        // Validate phone if provided
        if (phone && phone_signature) {
            const decryptor = new PayloadDecryptor(CLIENT_KEY);
            const result = decryptor.validateDecryption(phone, phone_signature);
            phoneValidation = typeof result.then === 'function' ? await result : result;
        }
        
        // Check if at least one verification is valid
        const emailValid = emailValidation?.isValid || false;
        const phoneValid = phoneValidation?.isValid || false;
        
        if (!emailValid && !phoneValid) {
            return res.status(400).json({
                success: false,
                message: 'No valid verification found'
            });
        }
        
        // Success response
        res.json({
            success: true,
            message: 'Verification successful!',
            verifications: {
                email: emailValid,
                phone: phoneValid
            },
            data: {
                email: emailValid ? email : null,
                phone: phoneValid ? phone : null
            }
        });
        
    } catch (error) {
        console.error('Validation error:', error);
        res.status(500).json({
            success: false,
            message: 'Server error during validation'
        });
    }
});

app.listen(3000, () => {
    console.log('Server running on port 3000');
});

Security Considerations

  • Always verify on the server: Client-side verification alone is not secure.
  • Store your client key securely: Use environment variables, do not hardcode the key.
  • Implement rate limiting: Prevent brute force attacks.
  • Set short TTL for verification: The decryptedData includes a timestamp to check recency.
  • HTTPS: Always use HTTPS in production environments.

Best Practice

After validating the signature, store the verification status in your user database. This allows you to check if a user is verified without requiring them to verify again.

API Reference

Client-Side Methods

MethodParametersDescription
initEmailVerification(selector, config)
selector: string
config: object
Initializes email verification widget in the specified DOM element.
initPhoneVerification(selector, config)
selector: string
config: object
Initializes phone verification widget in the specified DOM element.

Configuration Object

PropertyTypeRequiredDescription
siteIdstringYesYour unique site identifier from DEVOTP dashboard
onSuccessfunctionYesCallback function called when verification succeeds
onErrorfunctionYesCallback function called when verification fails

Server-Side API

MethodParametersReturn TypeDescription
new PayloadDecryptor(clientKey)clientKey: stringPayloadDecryptorCreates a new decryptor instance with your client key
validateDecryption(identifier, signature)
identifier: string
signature: string
ValidationResultValidates and decrypts a signature (may return Promise)

Troubleshooting

Common Issues

Verification Widget Not Showing

  • Check that your siteId is correct
  • Ensure your account is active and has sufficient credits
  • Check browser console for any JavaScript errors
  • Verify the DOM element exists before initializing

OTP Not Being Received

  • Check spam folder for email verification
  • Verify phone number format (include country code)
  • Check account status in the dashboard
  • Ensure sufficient credits in your account

Invalid Signature Errors

  • Ensure you are using the correct CLIENT_KEY
  • Check that the email/phone matches the one used for verification
  • Verify the signature has not expired (default TTL is 5 minutes)
  • Handle both sync and async validation results properly

SDK Loading Issues

  • Ensure the CDN script is loaded before your initialization code
  • Check that `window.Devotp` is available before calling methods
  • Verify network connectivity and CDN availability
  • Use browser developer tools to check for script loading errors

Debug Tips

  • Use browser console to check for JavaScript errors
  • Verify the DOM element selector is correct
  • Test with different email addresses and phone numbers
  • Check your DEVOTP dashboard for verification logs
  • Ensure proper error handling in your callback functions