Synchronous Implementation
This guide explains how to implement silent authentication using the synchronous approach, where your backend waits for a direct response after redirecting the user.
Note: if using a Synchronous implementation, switching on Verify capabilities on the application dashboard is optional, as this only switches the ability to receive status webhooks (that are not required for a Synchronous implementation).
The following diagram shows the necessary steps to implement the synchronous version of Silent Authentication:
Request Verification Code
To start the silent authentication process, make a request to /verify endpoint. In the following example, the workflow specifies that Verify will first attempt to use Silent Authentication. If for any reason the request fails, it will then fallback to email OTP.
Note: if using multiple channels, silent authentication must be the first channel in the workflow.
To run the example, replace the following variables in the sample code with your own values:
| Variable | Description |
|---|---|
JWT | Authenticates the API request using JWT. |
VERIFY_BRAND_NAME | The name of your company or service, shown to the user in the verification message. |
VONAGE_APPLICATION_PRIVATE_KEY_PATH | Private key of your application. |
VONAGE_APPLICATION_ID | Application ID of your application. |
VERIFY_NUMBER | The phone number to send the OTP to, in E.164 format (e.g., +44111223344). |
VERIFY_TO_EMAIL | The email to send the OTP to. |
Write the code
Add the following to request.sh:
curl -X POST "https://api.nexmo.com/v2/verify" \
-H "Authorization: Bearer $JWT"\
-H 'Content-Type: application/json' \
-d $'{
"brand": "'$VERIFY_BRAND_NAME'",
"workflow": [
{
"channel": "silent_auth",
"to": "'$VERIFY_NUMBER'"
},
{
"channel": "email",
"to": "'$VERIFY_EMAIL_TO'"
}
]
}'Run your code
Save this file to your machine and run it:
Prerequisites
npm install @vonage/server-sdk @vonage/verify2Create a file named send-request-with-fallback.js and add the following code:
const { Vonage } = require('@vonage/server-sdk');
const { Channels, SilentAuthChannel } = require('@vonage/verify2');
const vonage = new Vonage({
applicationId: VONAGE_APPLICATION_ID,
privateKey: VONAGE_APPLICATION_PRIVATE_KEY_PATH,
});Write the code
Add the following to send-request-with-fallback.js:
vonage.verify2.newRequest({
brand: VERIFY_BRAND_NAME,
workflow: [
{
channel: SilentAuthChannel.SILENT_AUTH,
to: VERIFY_NUMBER,
},
{
channel: Channels.EMAIL,
to: VERIFY_TO_EMAIL,
},
],
})
.then(({requestId}) => console.log(requestId))
.catch((err) => console.error(err));Run your code
Save this file to your machine and run it:
Prerequisites
Add the following to build.gradle:
implementation 'com.vonage:server-sdk-kotlin:2.1.1'Create a file named SendVerificationRequestWithFallback and add the following code to the main method:
val client = Vonage {
applicationId(VONAGE_APPLICATION_ID)
privateKeyPath(VONAGE_PRIVATE_KEY_PATH)
}Write the code
Add the following to the main method of the SendVerificationRequestWithFallback file:
val response = client.verify.sendVerification(VERIFY_BRAND_NAME) {
silentAuth(VERIFY_NUMBER)
email(VERIFY_TO_EMAIL)
}
println("Verification sent: ${response.requestId}")Run your code
We can use the application plugin for Gradle to simplify the running of our application. Update your build.gradle with the following:
apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''Run the following gradle command to execute your application, replacing com.vonage.quickstart.kt.verify with the package containing SendVerificationRequestWithFallback:
Prerequisites
Add the following to build.gradle:
implementation 'com.vonage:server-sdk:9.3.1'Create a file named SendRequestWithFallback and add the following code to the main method:
VonageClient client = VonageClient.builder()
.applicationId(VONAGE_APPLICATION_ID)
.privateKeyPath(VONAGE_PRIVATE_KEY_PATH)
.build();Write the code
Add the following to the main method of the SendRequestWithFallback file:
VerificationResponse response = client.getVerify2Client().sendVerification(
VerificationRequest.builder()
.addWorkflow(new SilentAuthWorkflow(VERIFY_NUMBER))
.addWorkflow(new EmailWorkflow(VERIFY_TO_EMAIL))
.brand(VERIFY_BRAND_NAME).build()
);
System.out.println("Verification sent: " + response.getRequestId());Run your code
We can use the application plugin for Gradle to simplify the running of our application. Update your build.gradle with the following:
apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''Run the following gradle command to execute your application, replacing com.vonage.quickstart.verify2 with the package containing SendRequestWithFallback:
Prerequisites
Install-Package VonageCreate a file named StartVerificationRequestWithFallback.cs and add the following code:
using Vonage;
using Vonage.Request;
using Vonage.VerifyV2.StartVerification;
using Vonage.VerifyV2.StartVerification.Email;
using Vonage.VerifyV2.StartVerification.SilentAuth;Add the following to StartVerificationRequestWithFallback.cs:
var credentials = Credentials.FromAppIdAndPrivateKeyPath(VONAGE_APPLICATION_ID, VONAGE_APPLICATION_PRIVATE_KEY_PATH);
var client = new VonageClient(credentials);Write the code
Add the following to StartVerificationRequestWithFallback.cs:
var request = StartVerificationRequest.Build()
.WithBrand(BRAND_NAME)
.WithWorkflow(SilentAuthWorkflow.Parse(TO_NUMBER))
.WithFallbackWorkflow(EmailWorkflow.Parse(TO_EMAIL))
.Create();
var response = await client.VerifyV2Client.StartVerificationAsync(request);Prerequisites
composer require vonage/clientCreate a file named request.php and add the following code:
Run your code
Save this file to your machine and run it:
Prerequisites
pip install vonage python-dotenvWrite the code
Add the following to send-request-with-fallback.py:
from vonage import Auth, Vonage
from vonage_verify import (EmailChannel, SilentAuthChannel,
StartVerificationResponse, VerifyRequest)
client = Vonage(
Auth(
application_id=VONAGE_APPLICATION_ID,
private_key=VONAGE_PRIVATE_KEY,
)
)
verify_request = VerifyRequest(
brand=VERIFY_BRAND_NAME,
workflow=[
SilentAuthChannel(to=VERIFY_NUMBER),
EmailChannel(to=VERIFY_TO_EMAIL, from_=VERIFY_FROM_EMAIL),
],
)
response: StartVerificationResponse = client.verify.start_verification(verify_request)
pprint(response)Run your code
Save this file to your machine and run it:
Prerequisites
gem install vonageCreate a file named request.rb and add the following code:
Run your code
Save this file to your machine and run it:
If the request is successful and the number is supported, you will receive a 200 Ok response containing a request_id and a check_url in the body:
{
"request_id": "c11236f4-00bf-4b89-84ba-88b25df97315",
"check_url": "https://api.nexmo.com/v2/verify/31eaf23d-b2db-4c42-9d1d-e847e75ab330/silent-auth/redirect"
}
Until the request expires or is cancelled, check_url can be used to perform a Silent Authentication check. Upon receiving this response, you need to make a
check_url from the mobile device you are trying to authenticate. In order for the Mobile Network Operator to properly verify the user, the GET request must be made over a mobile data connection. See Android and iOS Libraries for information on how to force a mobile connection.
Once you've made the
302 redirects depending on the territory and carrier the target device is using: HTTP/1.1 302 Found
Location: https://eu.api.silentauth.com/phone_check/v0.2/checks/31eaf23d-b2db-4c42-9d1d-e847e75ab330/redirect
Following the redirects will result in either a HTTP 200 or HTTP 409 response depending on whether the request is valid. If there is a problem with the network, you'll see a response like this:
HTTP/1.1 409 CONFLICT
Content-Type: application/json
{
"title": "Network error",
"detail": "The Silent Auth request could not be completed due to formatting or the carrier is not supported."
}
A full list of potential error codes can be found in the API Specification.
If the request is valid, you will receive an HTTP 200 response containing your request_id and a code:
{
"request_id": "c11236f4-00bf-4b89-84ba-88b25df97315",
"code": "si9sfG"
}
Note: To ensure a secure authentication check and mitigate against a potential man in the middle attack, store the original request_id and compare it with the request_id returned in the response. If the IDs don't match, the silent authentication check should be aborted. See our sample application for an example implementation of how to mitigate against the attack.
Check the Supplied Verification Code
Once the end-user receives the code, you must send a
/v2/verify/{request_id} endpoint, replacing {request_id} with the ID you received in the previous call. To run the example, replace the following variables in the sample code with your own values:
| Variable | Description |
|---|---|
JWT | Authenticates the API request using JWT. |
VERIFY_REQUEST_ID | The request_id received in the previous step. |
VONAGE_APPLICATION_PRIVATE_KEY_PATH | Private key of your application. |
VONAGE_APPLICATION_ID | Application ID of your application. |
VERIFY_CODE | The verification code received by the end-user |
Write the code
Add the following to check-verification-code.sh:
curl -X POST "https://api.nexmo.com/v2/verify/$VERIFY_REQUEST_ID" \
-H "Authorization: Bearer $JWT"\
-H 'Content-Type: application/json' \
-d $'{
"code": "'$VERIFY_CODE'"
}'Run your code
Save this file to your machine and run it:
Prerequisites
npm install @vonage/server-sdkCreate a file named check-verification-code.js and add the following code:
const { Vonage } = require('@vonage/server-sdk');
const vonage = new Vonage ({
applicationId: VONAGE_APPLICATION_ID,
privateKey: VONAGE_APPLICATION_PRIVATE_KEY_PATH,
});Write the code
Add the following to check-verification-code.js:
vonage.verify2.checkCode(VERIFY_REQUEST_ID, VERIFY_CODE)
.then((status) => console.log(`The status is ${status}`),
)
.catch((err) => console.error(err));Run your code
Save this file to your machine and run it:
Prerequisites
Add the following to build.gradle:
implementation 'com.vonage:server-sdk-kotlin:2.1.1'Create a file named CheckVerificationCode and add the following code to the main method:
val client = Vonage {
applicationId(VONAGE_APPLICATION_ID)
privateKeyPath(VONAGE_PRIVATE_KEY_PATH)
}Write the code
Add the following to the main method of the CheckVerificationCode file:
if (client.verify.request(VERIFY_REQUEST_ID).isValidVerificationCode(VERIFY_CODE)) {
println("Code matches.")
}Run your code
We can use the application plugin for Gradle to simplify the running of our application. Update your build.gradle with the following:
apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''Run the following gradle command to execute your application, replacing com.vonage.quickstart.kt.verify with the package containing CheckVerificationCode:
Prerequisites
Add the following to build.gradle:
implementation 'com.vonage:server-sdk:9.3.1'Create a file named CheckVerificationCode and add the following code to the main method:
VonageClient client = VonageClient.builder()
.applicationId(VONAGE_APPLICATION_ID)
.privateKeyPath(VONAGE_PRIVATE_KEY_PATH)
.build();Write the code
Add the following to the main method of the CheckVerificationCode file:
try {
client.getVerify2Client().checkVerificationCode(VERIFY_REQUEST_UUID, VERIFY_CODE);
System.out.println("SUCCESS - code matches!");
}
catch (VerifyResponseException ex) {
switch (ex.getStatusCode()) {
case 400: // Code does not match
case 404: // Already verified or not found
case 409: // Workflow does not support code
case 410: // Incorrect code provided too many times
case 429: // Rate limit exceeded
default: // Unknown or internal server error (500)
ex.printStackTrace();
}
}Run your code
We can use the application plugin for Gradle to simplify the running of our application. Update your build.gradle with the following:
apply plugin: 'application'
mainClassName = project.hasProperty('main') ? project.getProperty('main') : ''Run the following gradle command to execute your application, replacing com.vonage.quickstart.verify2 with the package containing CheckVerificationCode:
Prerequisites
Install-Package VonageCreate a file named VerifyCodeRequest.cs and add the following code:
using Vonage;
using Vonage.Request;Add the following to VerifyCodeRequest.cs:
var credentials = Credentials.FromAppIdAndPrivateKeyPath(VONAGE_APPLICATION_ID, VONAGE_APPLICATION_PRIVATE_KEY_PATH);
var client = new VonageClient(credentials);Write the code
Add the following to VerifyCodeRequest.cs:
var request = Vonage.VerifyV2.VerifyCode.VerifyCodeRequest.Build()
.WithRequestId(REQUEST_ID)
.WithCode(CODE)
.Create();
var response = await client.VerifyV2Client.VerifyCodeAsync(request);Prerequisites
composer require vonage/clientCreate a file named send_code.php and add the following code:
Run your code
Save this file to your machine and run it:
Prerequisites
pip install vonage python-dotenvWrite the code
Add the following to check-verification-code.py:
from vonage import Auth, Vonage
from vonage_verify import CheckCodeResponse
client = Vonage(
Auth(
application_id=VONAGE_APPLICATION_ID,
private_key=VONAGE_PRIVATE_KEY,
)
)
response: CheckCodeResponse = client.verify.check_code(
request_id=VERIFY_REQUEST_ID, code=VERIFY_CODE
)
print(response)Run your code
Save this file to your machine and run it:
Prerequisites
gem install vonageCreate a file named check.rb and add the following code:
Run your code
Save this file to your machine and run it:
Note: a code for a silent authentication workflow can only be checked once.
If the code is valid, you will receive a final response with the status completed:
{
"request_id": "31eaf23d-b2db-4c42-9d1d-e847e75ab330",
"status": "completed"
}
Or, if there is an error, you will see 'Invalid Code':
{
"title": "Invalid Code",
"type": "https://www.developer.vonage.com/api-errors/verify#invalid-code",
"detail": "The code you provided does not match the expected value.",
"instance": "bf0ca0bf927b3b52e3cb03217e1a1ddf"
}
At this point, your silent authentication verification is complete.