Login with OTP
The loginWithOtp method authenticates existing players using a one-time password (OTP) sent to their email or phone number. This is used after generating an OTP.
Prerequisites
Before calling loginWithOtp, you must:
- Generate an OTP using
genOtp - Player must have received the OTP via email/SMS
- Player must enter the OTP in your game
Basic Usage
Login with either email or phone number and the OTP.
Email Login
MoitribeSDK('my-game-id', 'loginWithOtp', {
emailid: 'player@example.com',
otp: '123456',
callback: (result) => {
if (result.success) {
console.log('Login successful');
startGame();
} else {
console.error('Login failed:', result.msg);
}
}
});
Phone Login
MoitribeSDK('my-game-id', 'loginWithOtp', {
phno: '+1234567890',
otp: '123456',
callback: (result) => {
if (result.success) {
console.log('Login successful');
startGame();
} else {
console.error('Login failed:', result.msg);
}
}
});
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
emailid | string | Either email or phone | Player's email address |
phno | string | Either email or phone | Player's phone number (E.164 format) |
otp | string | Yes | 6-digit OTP code |
callback | function | Yes | Called with login result |
You must provide either emailid or phno (matching what was used in genOtp), plus the otp code. Omitting required fields returns an error.
Response Format
The callback receives:
{
success: boolean; // true if login succeeded
msg?: string; // Error message (if failed)
statuscode?: number; // Error code (if failed)
}
Success Response
{
success: true
}
After successful login, the SDK's loginCallback (from initialization) is automatically called with player data.
Error Response
{
success: false,
msg: 'Invalid OTP',
statuscode: 102
}
Common Status Codes
| Code | Meaning | Action |
|---|---|---|
| 0 | Success | Player logged in |
| 102 | Invalid OTP | Ask player to re-enter OTP |
| 104 | OTP expired | Generate new OTP |
| 106 | Account not found | Use createWithOtp instead |
Complete Login Flow
Here's a complete email/OTP login flow:
const GAME_ID = 'my-game-id';
// Step 1: Player enters email
function showEmailLogin() {
const email = prompt('Enter your email:');
if (!email || !isValidEmail(email)) {
alert('Please enter a valid email');
return;
}
requestOtp(email);
}
// Step 2: Generate OTP
function requestOtp(emailid) {
showLoading('Sending verification code...');
MoitribeSDK(GAME_ID, 'genOtp', {
emailid: emailid,
callback: (result) => {
hideLoading();
if (result.success) {
showOtpInput(emailid);
} else {
alert('Failed to send code: ' + result.msg);
}
}
});
}
// Step 3: Player enters OTP
function showOtpInput(emailid) {
const otp = prompt(`Enter the 6-digit code sent to ${emailid}:`);
if (!otp || otp.length !== 6) {
alert('Please enter a valid 6-digit code');
showOtpInput(emailid); // Try again
return;
}
loginWithOtp(emailid, otp);
}
// Step 4: Verify OTP and login
function loginWithOtp(emailid, otp) {
showLoading('Verifying code...');
MoitribeSDK(GAME_ID, 'loginWithOtp', {
emailid: emailid,
otp: otp,
callback: (result) => {
hideLoading();
if (result.success) {
console.log('Login successful!');
// SDK automatically calls loginCallback with player data
} else {
handleLoginError(result, emailid);
}
}
});
}
// Step 5: Handle errors
function handleLoginError(result, emailid) {
if (result.statuscode === 102) {
alert('Invalid code. Please try again.');
showOtpInput(emailid); // Let player retry
} else if (result.statuscode === 104) {
alert('Code expired. Requesting a new one...');
requestOtp(emailid); // Generate new OTP
} else if (result.statuscode === 106) {
alert('Account not found. Please create an account.');
// Redirect to account creation
showCreateAccount(emailid);
} else {
alert('Login failed: ' + (result.msg || 'Unknown error'));
}
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
Receiving Player Data
After successful login, the SDK automatically calls the loginCallback defined during initialization:
MoitribeSDK('my-game-id', 'init', {
loginCallback: (result) => {
if (result.success) {
// This is called after successful loginWithOtp
const player = result.playerdata;
console.log('Player logged in:', player.name);
console.log('Player ID:', player.id);
console.log('Email:', player.emailid);
// Start game with player data
startGame(player);
}
}
});
TypeScript Example
import MoitribeSDK from '@veniso/moitribe-js';
interface LoginResult {
success: boolean;
msg?: string;
statuscode?: number;
}
interface LoginParams {
emailid?: string;
phno?: string;
otp: string;
callback: (result: LoginResult) => void;
}
const GAME_ID = 'my-game-id';
function loginWithEmailOtp(email: string, otp: string): void {
const params: LoginParams = {
emailid: email,
otp: otp,
callback: (result: LoginResult) => {
if (result.success) {
console.log('Login successful');
// SDK loginCallback will be called with player data
} else {
handleLoginError(result, email);
}
}
};
MoitribeSDK(GAME_ID, 'loginWithOtp', params);
}
function handleLoginError(result: LoginResult, email: string): void {
switch (result.statuscode) {
case 102:
showError('Invalid OTP. Please try again.');
break;
case 104:
showError('OTP expired. Please request a new one.');
break;
case 106:
showError('Account not found. Please create an account.');
navigateToCreateAccount(email);
break;
default:
showError(result.msg || 'Login failed. Please try again.');
}
}
OTP Input Validation
Validate OTP format before submitting:
function isValidOtp(otp) {
// Check if 6 digits
return /^\d{6}$/.test(otp);
}
function handleOtpSubmit(emailid, otp) {
// Remove any spaces or hyphens
const cleanedOtp = otp.replace(/[\s-]/g, '');
if (!isValidOtp(cleanedOtp)) {
showError('Please enter a valid 6-digit code');
return;
}
MoitribeSDK('my-game-id', 'loginWithOtp', {
emailid: emailid,
otp: cleanedOtp,
callback: handleLoginResult
});
}
Auto-Submit OTP
Automatically submit when player enters 6 digits:
function showOtpInputForm(emailid) {
const input = document.getElementById('otp-input');
input.addEventListener('input', (e) => {
const otp = e.target.value;
// Auto-submit when 6 digits entered
if (otp.length === 6 && isValidOtp(otp)) {
submitOtp(emailid, otp);
}
});
}
function submitOtp(emailid, otp) {
showLoading('Verifying...');
MoitribeSDK('my-game-id', 'loginWithOtp', {
emailid: emailid,
otp: otp,
callback: (result) => {
hideLoading();
if (result.success) {
console.log('Login successful');
} else {
showError(result.msg || 'Invalid code');
clearOtpInput();
}
}
});
}
Resend OTP
Allow players to request a new OTP:
function showOtpInputWithResend(emailid) {
let canResend = false;
let resendTimer = 30; // 30 second cooldown
// Start cooldown timer
const interval = setInterval(() => {
resendTimer--;
updateResendButton(`Resend in ${resendTimer}s`);
if (resendTimer <= 0) {
clearInterval(interval);
canResend = true;
updateResendButton('Resend Code');
}
}, 1000);
// Handle resend click
document.getElementById('resend-btn').onclick = () => {
if (canResend) {
resendOtp(emailid);
}
};
}
function resendOtp(emailid) {
MoitribeSDK('my-game-id', 'genOtp', {
emailid: emailid,
callback: (result) => {
if (result.success) {
showMessage('New code sent!');
} else {
showError('Failed to send new code');
}
}
});
}
Handling "Account Not Found"
If the OTP is valid but no account exists, redirect to account creation:
MoitribeSDK('my-game-id', 'loginWithOtp', {
emailid: 'newplayer@example.com',
otp: '123456',
callback: (result) => {
if (result.success) {
console.log('Login successful');
} else if (result.statuscode === 106) {
// Account doesn't exist - offer to create one
showDialog({
title: 'Account Not Found',
message: 'Would you like to create an account?',
buttons: [
{
text: 'Create Account',
action: () => {
// OTP is still valid - use it for account creation
createAccountWithOtp('newplayer@example.com', '123456');
}
},
{
text: 'Cancel',
action: () => showEmailLogin()
}
]
});
}
}
});
Best Practices
1. Clear Error Messages
Provide helpful feedback for each error type:
function getErrorMessage(statuscode) {
const messages = {
102: 'The code you entered is incorrect. Please try again.',
104: 'This code has expired. Please request a new one.',
106: 'No account found with this email. Please create an account.',
};
return messages[statuscode] || 'Login failed. Please try again.';
}
2. OTP Expiration Warning
Warn players that OTPs expire:
MoitribeSDK('my-game-id', 'genOtp', {
emailid: email,
callback: (result) => {
if (result.success) {
showMessage(
'Code Sent',
'A 6-digit code was sent to your email. It will expire in 10 minutes.'
);
}
}
});
3. Rate Limiting
Track failed attempts and implement delays:
let failedAttempts = 0;
MoitribeSDK('my-game-id', 'loginWithOtp', {
emailid: email,
otp: otp,
callback: (result) => {
if (result.success) {
failedAttempts = 0;
} else {
failedAttempts++;
if (failedAttempts >= 3) {
showError('Too many failed attempts. Please wait 1 minute.');
setTimeout(() => {
failedAttempts = 0;
}, 60000);
}
}
}
});
OTPs are typically valid for 10-15 minutes. If a player needs more time, implement a "Resend Code" button to generate a fresh OTP.
Next Steps
After successful login:
- Get Profile - Access player profile data
- Update Profile - Modify player information
Related authentication topics:
- Generate OTP - Send OTP to players
- Create Account with OTP - Register new players
- Check Authentication - Verify login status
- Authentication Overview - Authentication concepts