Documentation | Settings | Request behavior | Source
A Node.js Azure Function implementing the shared HTTP contract with one provider per deployment.
Sample deployment: follow the five-step guide, then complete provider authentication and validation.
Custom package development: follow these steps from javascript/:
- Create the local settings below. Select a fixed provider ID from providers/, configure it, and complete provider authentication.
- Install package.json dependencies, run its offline test script, and start Core Tools from this folder. Bind only to loopback, without tunnels: Core Tools has no Easy Auth.
- For manual deployment, package this app, inspect it for secrets, and complete the Easy Auth trust checklist. Keep Easy Auth enabled for SendOtp, then run authorized deployed checks to verify platform authentication.
Regional continuity: use the Front Door guide.
Run Core Tools from javascript/. Create an untracked local.settings.json beside
host.json, not inside src/. Start from the
shared sample. For local evaluation, start Azurite and replace
the test-key placeholder in this minimal setup:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"EPP_DECRYPTION_KEY_PEM": "<base64 of your local test private PEM>"
}
}For live delivery, use the shared settings table
for EPP_PROVIDER_NAME, both channel endpoints, authentication, and adapter-specific options.
Keep Values as strings, including EPP_PROVIDER_TIMEOUT_MS, for example "1500".
Replace the placeholders. Store API keys in Key Vault. Each selected channel requires a valid
endpoint. An invalid or missing endpoint returns an error without using the other channel.
Core Tools copies Values into the process environment. Direct Node processes and offline tests
do not load the file. Restart after edits. Use a local test PEM because Core Tools cannot resolve
Key Vault references locally. Keep Azurite settings local.
In Azure, configure the same app settings and use a Key Vault reference for the private PEM. Provider secrets use managed identity, not a developer CLI login. Keep local evaluation on loopback.
POST /api/SendOtp follows the shared request/response contract.
Easy Auth authenticates the caller. The handler then validates and decrypts the payload. It never
forwards or returns the incoming Authorization header.
Use mode: 2 or "evaluation" to validate
authentication and decryption without a provider send. Live success confirms acceptance,
not handset receipt. Check a timeout before retrying.
For built-in message and voice mapping, see Soprano and Telesign.
To add Twilio, follow the Twilio integration guide. Keep caller authentication and public responses in the shared handler.
For diagnostics, use Application Insights and the JavaScript event queries.
The cache switches and defaults apply here. Disabling the selected cache removes startup preparation, polling, and cross-request reuse, not live credential acquisition.
With caching enabled, API keys use Key Vault and lru-cache. OAuth uses managed identity and the
Azure Identity SDK. A 30-second refresh loop and one in-flight acquisition support warm reads. See the
credential caching guide.
| Source | Purpose |
|---|---|
| src/functions/SendOtp.js | Explicit HTTP orchestration and startup/termination hooks |
| src/functions/config.js | Shared deployment settings |
| src/functions/entraPayload.js | Validated Microsoft Entra ID envelope and exact contract reasons |
| src/functions/delivery.js | Validated decrypted context and immutable provider-neutral delivery |
| src/functions/jwe.js | Flat JWE validation/decryption with pinned algorithms and PEM key cache |
| src/functions/providerTransport.js | HTTPS validation, bounded fetch, body read, JSON parse and manual redirects |
| src/functions/providerResult.js | Provider result and endpoint outcome model |
| src/functions/logging.js | Immutable request context and fixed privacy-safe structured events |
| src/functions/credentials.js | CredentialTokenService, ApiKeyCache, AccessTokenCache and refresh lifecycle |
| src/functions/providers/ | Fixed lookup and provider-owned credential/request/response rules |
| test/ | Representative offline checks |
To add a provider, implement its fixed name, authenticationMode, credentialSpec,
createRequest, and interpretResponse in the provider folder. Then add it to the switch in
providers/index.js. interpretResponse returns a
ProviderResult containing the provider-owned outcome, endpoint HTTP status and one safe fixed
failure classification. Raw API JSON stays inside the provider. See
production readiness when planning a live service.