Overview
Doshi webview authentication uses a secure two-step process:
- Generate a nonce token by calling the Doshi API with your API key
- Pass the token to the iframe using postMessage or query parameters
IP Whitelisting Required: Your server’s IP address must be whitelisted to access the Doshi API. Contact [email protected] with your server IP addresses to get started.
Get API Key & Whitelist IP
Contact [email protected] to:
- Receive your API key
- Whitelist your server IP address(es)
Generate Nonce Token
Call the authentication endpoint with your API key from your whitelisted server
Embed Webview
Pass the nonce token to the Doshi Frontend using postMessage or query parameters
User Signs In
Doshi handles the sign-in process, including 2FA if enabled
Authentication Flow
Step 1: Generate Nonce Token
Call the authentication endpoint with your API key:
curl -X POST https://production-doshi-api-8kq2.encr.app/client/auth/custom-token \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"partnerUserId": "partner_123",
"firstName": "John",
"lastName": "Doe",
"branchId": "branch_789"
}'
API Parameters
Required (at least one):
email - User’s email address
partnerUserId - Your internal user ID
Optional:
firstName - User’s first name
lastName - User’s last name
branchId - Branch or location identifier
You must provide either email OR partnerUserId (or both). All other fields are optional.
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
See the full API reference for details.
Step 2: Pass Token to Doshi Frontend
Pass the nonce token to the Doshi Frontend using one of two methods:
Frontend Parameters
Required:
token - The nonce token from the API
Optional:
email - User’s email address
segment - For handling multiple learning paths
branchId - Branch or location identifier
2FA Parameters (Optional)
When 2FA is enabled, pass these additional parameters:
All 2FA fields are required when is2FaEnabled is true:
is2FaEnabled - Set to true
dob - Date of birth (YYYY-MM-DD)
organizationId - Your organization ID
partnerUserId - Your internal user ID
firstName - User’s first name
lastName - User’s last name
The nonce token received from the API
User’s email address (optional)
Used for handling multiple learning paths under the same organization (optional)
Branch or location identifier (optional)
Set to true to enable 2FA flow (optional, but if true, all 2FA fields below are required)
User’s date of birth - YYYY-MM-DD format (required when is2FaEnabled is true)
Your organization ID (required when is2FaEnabled is true)
Your internal user ID (required when is2FaEnabled is true)
User’s first name (required when is2FaEnabled is true)
User’s last name (required when is2FaEnabled is true)
When 2FA is enabled, the Doshi Frontend automatically handles the OTP send and verification flow. You don’t need to call the OTP endpoints separately.
Step 3: Session Management
Once authenticated, the Doshi Frontend automatically manages the session:
- ID Token TTL: 1 hour
- Refresh Token TTL: 12 hours
- Auto-refresh: Tokens are refreshed automatically
No additional action required from your application!
Quick Example
React with postMessage
import React, { useEffect, useState } from "react";
const DoshiEmbed = () => {
const [token, setToken] = useState<string | null>(null);
useEffect(() => {
// Step 1: Get nonce token from API
async function authenticate() {
const response = await fetch('https://production-doshi-api-8kq2.encr.app/client/auth/custom-token', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '[email protected]', // Required (or partnerUserId)
partnerUserId: 'partner_123', // Optional (but one of email/partnerUserId required)
branchId: 'branch_789' // Optional
})
});
const data = await response.json();
setToken(data.token);
}
authenticate();
}, []);
useEffect(() => {
if (!token) return;
// Step 2: Listen for PING from Doshi Frontend
const handleMessage = (event: MessageEvent) => {
if (event.origin !== 'https://embed.doshi.app') return;
const data = typeof event.data === "string"
? JSON.parse(event.data)
: event.data;
if (data.type === "PING") {
// Step 3: Send token to Doshi Frontend
const iframe = document.querySelector("iframe");
if (iframe?.contentWindow) {
iframe.contentWindow.postMessage(
JSON.stringify({
token, // Required
email: '[email protected]', // Optional
segment: 'premium', // Optional
branchId: 'branch_789', // Optional
type: "AUTH"
}),
"https://embed.doshi.app"
);
}
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, [token]);
if (!token) {
return <div>Loading...</div>;
}
return (
<iframe
src="https://embed.doshi.app"
className="w-full h-screen"
frameBorder="0"
allowFullScreen
/>
);
};
export default DoshiEmbed;
React with Query Parameters
import React, { useEffect, useState } from "react";
const DoshiEmbed = () => {
const [iframeUrl, setIframeUrl] = useState<string | null>(null);
useEffect(() => {
async function authenticate() {
// Step 1: Get nonce token
const response = await fetch('https://production-doshi-api-8kq2.encr.app/client/auth/custom-token', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '[email protected]', // Required (or partnerUserId)
partnerUserId: 'partner_123' // Optional
})
});
const data = await response.json();
// Step 2: Build URL with token
const params = new URLSearchParams({
token: data.token, // Required
email: '[email protected]', // Optional
segment: 'premium', // Optional
branchId: 'branch_789' // Optional
});
setIframeUrl(`https://embed.doshi.app?${params.toString()}`);
}
authenticate();
}, []);
if (!iframeUrl) {
return <div>Loading...</div>;
}
return (
<iframe
src={iframeUrl}
className="w-full h-screen"
frameBorder="0"
allowFullScreen
/>
);
};
export default DoshiEmbed;
With 2FA Enabled
const authData = {
token: data.token, // Required
email: '[email protected]', // Optional
segment: 'premium', // Optional
branchId: 'branch_789', // Optional
// All fields below are required when is2FaEnabled is true
is2FaEnabled: true,
dob: '1990-01-15',
organizationId: 'org_123',
partnerUserId: 'partner_123',
firstName: 'John',
lastName: 'Doe'
};
// The Doshi Frontend will automatically show OTP screen and handle verification
Next Steps
Need Help?