2.2.2.1 C#/.NET
VerifySpeed C#/.NET Client Library Documentation
The VerifySpeed .NET Client Library allows you to seamlessly integrate user verification features into your application. With support for multiple verification methods like Telegram, WhatsApp, and SMS, you can ensure a secure and reliable verification process for your users.
Setup
Step 1: Intall the Package
First, make sure you have installed the VerifySpeed package:
dotnet add package VerifySpeed.VSCSharp
Step 2: Service Registration
Next, add the VerifySpeed services to your application's dependency injection container in the Startup.cs or Program.cs file.
- .NET 6+
- .NET 5
using VSCSharp;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
// Register VerifySpeed services with your server key.
builder.Services.AddVerifySpeed("YOUR_SERVER_KEY");
// Add other services
WebApplication app = builder.Build();
// Add your middlewares
app.Run();
using VSCSharp;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Register VerifySpeed services with your server key
services.AddVerifySpeed("YOUR_SERVER_KEY");
// Add other services
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Add your middlewares
}
}
Usage
Below are examples of how to use the VerifySpeed client in your C# application.
Please read Verification Flow to understand the verification process.
1. Initializing the Client
Before creating a verification, you need to initialize the verification process to retrieve the available verification methods.
using System;
using System.Threading.Tasks;
using VSCSharp.Clients;
using VSCSharp.Exceptions;
public class VerifySpeedExample
{
private readonly IVerifySpeedClient verifySpeedClient;
public VerifySpeedExample(IVerifySpeedClient verifySpeedClient)
{
this.verifySpeedClient = verifySpeedClient;
}
public async Task InitializeVerificationAsync()
{
try
{
//TODO: Replace with the actual remote client IP address.
string clientIp = "192.168.1.1";
Initialization initialization = await verifySpeedClient.InitializeAsync(clientIp);
Console.WriteLine("Available Verification Methods:");
foreach (Method availableMethod in initialization.AvailableMethods)
{
Console.WriteLine($"- {availableMethod.DisplayName} ({availableMethod.MethodName})");
}
// in most cases, you may return the available methods to client.
}
catch (FailedInitializationException exeption)
{
Console.WriteLine($"Initialization failed: {exeption.Message}");
}
}
}
2. Creating a Verification
Once initialized, you can create a verification using the desired method (e.g., Telegram Message, WhatsApp OTP).
NOTE: Please read Verification Flow and Verification Methods to understand the verification process.
CreateVerificationAsync parameters
| Parameter | Required | Description |
|---|---|---|
methodName | Yes | Verification method identifier (e.g., telegram-message, whatsapp-otp). |
clientIPv4Address | Yes | The client's IPv4 address, sent as a request header. |
phoneNumber | For OTP methods | User's phone number in E.164 format. Required when methodName is an OTP method (whatsapp-otp, telegram-otp, sms-otp). VerifySpeed sends a one-time password to this number. Omit for message-based methods. |
language | No | Language for the verification flow (e.g., en, ar, ckb). Defaults to en. |
If methodName is an OTP type and phoneNumber is omitted, the client throws FailedCreateVerificationException with the message "phoneNumber is required for OTP method types".
/// <summary>
/// Creates a verification.
/// </summary>
/// <param name="methodName">The verification method identifier (e.g., "whatsapp-message", "whatsapp-otp").</param>
/// <param name="clientIPv4Address">The client's IPv4 address to include in the request header.</param>
/// <param name="phoneNumber">The user's phone number in E.164 format (e.g., "+14255552673"). Required when <paramref name="methodName"/> is an OTP method ("whatsapp-otp", "telegram-otp", or "sms-otp"); VerifySpeed sends a one-time password to this number. Omit for message-based methods.</param>
/// <param name="language">The language to use for the verification process (e.g., "en", "ar", "ckb"). Optional; defaults to English.</param>
/// <returns>A <see cref="CreatedVerificationResponse"/> object that represents the created verification.</returns>
/// <exception cref="FailedCreateVerificationException">Thrown when the verification creation fails, or when <paramref name="phoneNumber"/> is omitted for an OTP method.</exception>
Task<CreatedVerificationResponse> CreateVerificationAsync(
string methodName,
string clientIPv4Address,
string? phoneNumber = null,
string? language = null
);
Message-based method
For message-based methods (whatsapp-message, telegram-message), omit phoneNumber. The response includes a DeepLink for the client app.
using System;
using System.Threading.Tasks;
using VSCSharp.Clients;
using VSCSharp.Exceptions;
public class MessageVerificationCreationExample
{
private readonly IVerifySpeedClient verifySpeedClient;
public MessageVerificationCreationExample(IVerifySpeedClient verifySpeedClient)
{
this.verifySpeedClient = verifySpeedClient;
}
public async Task CreateVerificationAsync()
{
try
{
//TODO: Replace with the actual remote client IP address.
string clientIp = "192.168.1.1";
CreatedVerificationResponse createdVerification = await verifySpeedClient.CreateVerificationAsync(
methodName: "telegram-message",
clientIPv4Address: clientIp,
language: "ar"
);
Console.WriteLine($"Verification Method: {createdVerification.MethodName}");
Console.WriteLine($"Verification Key: {createdVerification.VerificationKey}");
Console.WriteLine($"Deep Link: {createdVerification.DeepLink}");
// Return VerificationKey and DeepLink to your mobile/web app
}
catch (FailedCreateVerificationException exeption)
{
Console.WriteLine($"Failed to create verification: {exeption.Message}");
}
}
}
OTP-based method
For OTP methods (whatsapp-otp, telegram-otp, sms-otp), pass phoneNumber. VerifySpeed sends the OTP to that number; your client app collects the code from the user and completes verification through the SDK.
public async Task CreateOtpVerificationAsync()
{
try
{
string clientIp = "192.168.1.1";
CreatedVerificationResponse createdVerification = await verifySpeedClient.CreateVerificationAsync(
methodName: "whatsapp-otp",
clientIPv4Address: clientIp,
phoneNumber: "+14255552673",
language: "en"
);
Console.WriteLine($"Verification Key: {createdVerification.VerificationKey}");
// DeepLink is null for OTP methods — return VerificationKey to your client app
}
catch (FailedCreateVerificationException exeption)
{
Console.WriteLine($"Failed to create verification: {exeption.Message}");
}
}
3. Verifying Verification Tokens (Local Method)
Local verification approach: The EncryptionTool class allows you to verify verification tokens directly on your server without making additional API calls. This method is faster and gives you full control over the verification process, but it cannot detect token reuse.
- Client's Built-in Method
- EncryptionTool Extension Method
The IVerifySpeedClient also provides a built-in verification method that uses your configured server key:
public class ClientVerificationExample
{
private readonly IVerifySpeedClient verifySpeedClient;
public ClientVerificationExample(IVerifySpeedClient verifySpeedClient)
{
verifySpeedClient = verifySpeedClient;
}
public void VerifyTokenUsingClient(string encryptedToken)
{
try
{
// Uses the server key configured during service registration
VerificationResult result = verifySpeedClient.VerifiedVerificationToken(encryptedToken);
Console.WriteLine($"Decrypted Phone Number: {result.PhoneNumber}");
Console.WriteLine($"Verification Method: {result.MethodName}");
Console.WriteLine($"Date of Verification: {result.DateOfVerification}");
Console.WriteLine($"Verification Key: {result.VerificationKey}");
// Process the verified user
}
catch (InvalidVerificationTokenException ex)
{
Console.WriteLine($"Token validation failed: {ex.Message}");
}
catch (FailedDecryptingVerificationTokenException ex)
{
Console.WriteLine($"Token verification failed: {ex.Message}");
}
}
}
This approach is convenient when you want to use the server key that was configured during service registration without having to pass it explicitly.
The VerifiedVerificationToken method is implemented as an extension method on the string type, making it easy to use:
// Direct usage on the encrypted token string
string encryptedToken = "your_encrypted_token_here";
string serverKey = "your_server_key_here";
VerificationResult result = encryptedToken.VerifiedVerificationToken(serverKey);
// Or using the EncryptionTool class directly
var encryptionTool = new EncryptionTool();
VerificationResult result2 = encryptionTool.VerifiedVerificationToken(encryptedToken, serverKey);
This approach gives you more flexibility and control over the verification process.
4. Verifying a Token via API (Enhanced Security Method)
Enhanced Security Approach: The API verification method provides additional security features that local verification cannot offer. When you verify tokens through the VerifySpeed API, you receive information about whether this token has been verified for the first time, which helps prevent token reuse attacks.
Security Benefit: The API method provides firstTimeVerified information that indicates whether the token has been reused or not, making it more secure against replay attacks than local verification alone.
using System;
using System.Threading.Tasks;
using VSCSharp.Clients;
using VSCSharp.Exceptions;
public class TokenVerificationExample
{
private readonly IVerifySpeedClient verifySpeedClient;
public TokenVerificationExample(IVerifySpeedClient verifySpeedClient)
{
verifySpeedClient = verifySpeedClient;
}
public async Task VerifyTokenAsync(string token)
{
try
{
// API verification provides additional security information
GetVerificationResultResponse result = await verifySpeedClient.VerifyTokenAsync(token);
Console.WriteLine($"Verified Phone Number: {result.PhoneNumber}");
Console.WriteLine($"Verification Method: {result.MethodName}");
Console.WriteLine($"Date of Verification: {result.DateOfVerification}");
Console.WriteLine($"Verification Key: {result.VerificationKey}");
// Check if this is the first time this token has been verified
if (result.FirstTimeVerified == "true")
{
Console.WriteLine("✅ This token is being verified for the first time - secure");
// Proceed with your business logic
ProcessVerifiedUser(result.PhoneNumber, result.MethodName, result.DateOfVerification, result.VerificationKey);
}
else
{
Console.WriteLine("⚠️ This token has been verified before - potential security risk");
// Handle token reuse scenario
HandleTokenReuse(result.PhoneNumber, result.VerificationKey);
}
}
catch (FailedVerifyingTokenException exeption)
{
Console.WriteLine($"Token verification failed: {exeption.Message}");
}
}
private void ProcessVerifiedUser(string phoneNumber, string methodName, DateTime verificationDate, string verificationKey)
{
// Implement your business logic here for first-time verification
Console.WriteLine($"Processing verified user: {phoneNumber} via {methodName}");
}
private void HandleTokenReuse(string phoneNumber, string verificationKey)
{
// Implement security measures for token reuse
Console.WriteLine($"Token reuse detected for phone: {phoneNumber}, key: {verificationKey}");
// Log the incident, block the request, or take other security measures
}
}
Models
Initialization Response
-
Initialization: Contains a list of available verification methods.
public record Initialization{public List<Method> AvailableMethods { get; init; } = new();}public record Method{public string MethodName { get; init; } = null!;public string DisplayName { get; init; } = null!;}
Created Verification
-
CreatedVerificationResponse: Details of the created verification, including its key and method name.
DeepLinkis returned for message-based methods (whatsapp-message,telegram-message) andnullfor OTP methods (whatsapp-otp,telegram-otp,sms-otp).public record CreatedVerificationResponse{public string MethodName { get; init; } = null!;public string VerificationKey { get; init; } = null!;public string? DeepLink { get; init; }}
Verification Result
-
VerificationResult: Represents the outcome of verifying a user's token.
/// <summary>/// Represents the result of a verification process, including the method used,/// the date of verification, and the verified phone number./// </summary>public record VerificationResult{/// <summary>/// Gets the name of the verification method used./// For example, "whatsapp-message", or "sms-otp"./// </summary>[JsonPropertyName("methodName")]public string MethodName { get; init; } = null!;/// <summary>/// Gets the date and time when the verification was completed./// </summary>[JsonPropertyName("dateOfVerification")]public DateTime DateOfVerification { get; init; }/// <summary>/// Gets the verified phone number./// </summary>[JsonPropertyName("phoneNumber")]public string PhoneNumber { get; init; } = null!;/// <summary>/// Gets the verification key./// </summary>[JsonPropertyName("verificationKey")]public string VerificationKey { get; init; } = null!;}
API Verification Result
-
GetVerificationResultResponse: Represents the result of API verification, including additional security information.
/// <summary>/// Represents the result of a verification process/// </summary>public record GetVerificationResultResponse{/// <summary>/// Gets the name of the verification method used./// For example, "whatsapp-message", or "sms-otp"./// </summary>[JsonPropertyName("methodName")]public string MethodName { get; init; } = null!;/// <summary>/// Gets the date and time when the verification was completed./// </summary>[JsonPropertyName("dateOfVerification")]public DateTime DateOfVerification { get; init; }/// <summary>/// Gets the verified phone number./// </summary>[JsonPropertyName("phoneNumber")]public string PhoneNumber { get; init; } = null!;/// <summary>/// Gets the verification key./// </summary>[JsonPropertyName("verificationKey")]public string VerificationKey { get; init; } = null!;/// <summary>/// Indicates whether this is the first time the token has been verified. False means it has been verified before by VerifySpeed./// </summary>[JsonPropertyName("firstTimeVerified")]public string FirstTimeVerified { get; init; } = null!;}
Exceptions
Handle the following exceptions
- FailedInitializationException: Thrown when initialization fails.
- FailedCreateVerificationException: Thrown when verification creation fails.
- FailedVerifyingTokenException: Thrown when token verification fails.
- InvalidVerificationTokenException: Thrown when the verification token is null, empty, or has an invalid format.
- FailedDecryptingVerificationTokenException: Thrown when token verification fails due to cryptographic errors.
API Example
Here is an use case example of this library for varifying users phone number.
using Microsoft.AspNetCore.Mvc;
using VSCSharp.Clients;
using VSCSharp.Models.Commons;
using VSCSharp.Enums;
[ApiController]
[Route("api/[controller]")]
public class VerificationController : ControllerBase
{
private readonly IVerifySpeedClient verifySpeedClient;
public VerificationController(IVerifySpeedClient verifySpeedClient)
{
verifySpeedClient = verifySpeedClient;
}
[HttpPost("initialize")]
public async Task<IActionResult> PostVerificationInitialization()
{
try
{
var clientIp = HttpContext.Connection.RemoteIpAddress?.ToString();
// NOTE: If your API is behind proxy or load balancer, get client's IP from 'X-Forwarded-For' header
Initialization initialization = await verifySpeedClient.InitializeAsync(clientIp);
return Ok(initialization);
}
catch (Exception exeption)
{
return BadRequest(exeption.Message);
}
}
[HttpPost("create")]
public async Task<IActionResult> PostVerificationCreation([FromBody] PostVerificationCreationRequest request)
{
try
{
var clientIp = HttpContext.Connection.RemoteIpAddress?.ToString();
// NOTE: If your API is behind proxy or load balancer, get client's IP from 'X-Forwarded-For' header
CreatedVerificationResponse verification = await verifySpeedClient.CreateVerificationAsync(
methodName: request.MethodType,
clientIPv4Address: clientIp,
phoneNumber: request.PhoneNumber,
language: request.Language
);
return Ok(verification);
}
catch (Exception exeption)
{
return BadRequest(exeption.Message);
}
}
[HttpGet("verify/{token}")]
public async Task<IActionResult> GetVerificationResult(string token)
{
try
{
// Option 1: Use local verification (faster, but no reuse detection)
// Uses the server key configured during service registration
VerificationResult result = verifySpeedClient.VerifiedVerificationToken(token);
// Option 2: Use API verification (slower, but provides reuse detection)
// GetVerificationResultResponse result = await verifySpeedClient.VerifyTokenAsync(token);
// Now you can use verified phone number inside result object
Console.WriteLine($"Verified Phone Number: {result.PhoneNumber}");
Console.WriteLine($"Verification Key: {result.VerificationKey}");
return Ok(result);
}
catch (InvalidVerificationTokenException ex)
{
return BadRequest($"Invalid token: {ex.Message}");
}
catch (FailedDecryptingVerificationTokenException ex)
{
return BadRequest($"Verification failed: {ex.Message}");
}
catch (Exception exeption)
{
return BadRequest(exeption.Message);
}
}
}
public class PostVerificationCreationRequest
{
[Required]
public string MethodType { get; set; }
/// <summary>
/// Required for OTP methods (whatsapp-otp, telegram-otp, sms-otp).
/// E.164 format, e.g. +14255552673.
/// </summary>
public string? PhoneNumber { get; set; }
public string? Language { get; set; }
}
License
This package is distributed under the MIT License.