Skip to content

Latest commit

 

History

History
109 lines (91 loc) · 7.33 KB

File metadata and controls

109 lines (91 loc) · 7.33 KB

External Phone Provider Function — JavaScript

A Node.js Azure Function implementing the shared contract: one dispatch engine and one selected provider per deployment. API-specific behavior stays in registered adapters.

Setup

  1. Follow customer onboarding. Choose a registered adapter and set EPP_PROVIDER_NAME to its manifest id; <adapter-id> is a placeholder, not a default.
  2. Consult the selected adapter and its manifest in src/functions/providers/ for required credentials and options. Store credential values under the manifest's Key Vault secret names, grant the Function's managed identity Key Vault Secrets User, and configure the matching endpoint and required options. This guide does not duplicate individual API contracts.
  3. Use ../docs/local.settings.sample.json as a starting point, replacing placeholders with the selected adapter's settings. Keep local settings private at the app root beside host.json, with FUNCTIONS_WORKER_RUNTIME=node.
  4. Configure decryption from the shared catalog. Follow platform trust setup: Easy Auth is the only caller-authentication gate before the anonymous Function. Enable requireAuthentication=true, unauthenticatedClientAction=Return401 and requireHttps=true; pin the trusted tenant issuer, endpoint-app allowedAudiences and a nonempty allowedApplications list for the authorized SAS caller. Do not exclude SendOtp. There is no backup application token validation; never expose the endpoint to the public internet with Easy Auth disabled or bypassed.
  5. Install dependencies from package.json, run its offline test script and start the local Functions host from this folder. Core Tools has no Easy Auth: bind only to loopback, with no tunnels or public forwarding. Publish this app folder only, preserving dependencies and observing .funcignore; inspect the package before upload. Offline tests cover application behavior, not platform authentication; run the separate deployed security checks.

Environment configuration

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, add EPP_PROVIDER_NAME, EPP_PROVIDER_ENDPOINT and KEY_VAULT_URL to Values. Add EPP_PROVIDER_ACCOUNT_NAME and any adapter-specific options only when required. Optional EPP_PROVIDER_TIMEOUT_MS is a string such as "1500". Replace placeholders; do not put API keys in this file. See the complete variable table.

Core Tools copies Values into the process environment; direct Node processes and the offline tests do not automatically load this file. AppConfig reads process.env once per call to readConfig(). Restart the host after changing settings. Configure any local host storage other than Azurite separately; do not copy a local emulator connection into Azure. Core Tools does not resolve Key Vault references locally; supply the local test PEM or base64 PEM directly.

Older private settings may contain DEFAULT_PROVIDER, ENDPOINT_TIMEOUT_MS, REQUIRE_AUTH, EXPECTED_AUDIENCE, ISSUER_TENANT_ID, EUDB, or per-provider *_ENDPOINT entries. Those do not configure the current shared engine. Use EPP_PROVIDER_NAME, EPP_PROVIDER_ENDPOINT and EPP_PROVIDER_TIMEOUT_MS instead; configure caller authentication in Easy Auth. Keep adapter options that are actually read, such as a service-plan ID or voice selection. Private integration helpers may load settings from another location or use test credential variables, but the Function itself does not.

For the omnimsg adapter, the configured base ends in /cgpapi; the adapter appends /messages/omnimsg for SMS and voice. QA4 is the test environment; select the provider-approved production base separately. The base URL is not hard-coded and changing local settings does not change an already deployed app.

For Azure, set these application variables on the Function App/slot's Environment variables → App settings page and use a Key Vault reference for the private PEM. The provider-secret resolver uses managed identity; signing into the CLI locally does not supply that identity. Local evaluation avoids provider lookup, while tests inject mocked credentials and HTTP. Keep the local endpoint on loopback.

Request behavior

Easy Auth authenticates and authorizes the caller before POST /api/SendOtp; the anonymous handler validates the envelope and decrypts the JWE, without parsing or echoing incoming Authorization. JWE does not authenticate SAS: anyone with the public key can encrypt a request, and a fixed nonce is not authentication. Request mode, channel, ttlSeconds and tenantId are request data, not environment settings or sources of identity trust. The caller-rendered message is forwarded unchanged; the endpoint does not guess a passcode.

For non-delivery validation, use incoming mode: 2 or mode: "evaluation". This generic shutter works for every provider without provider configuration, provider Key Vault reads or provider HTTP; platform authentication on Azure and handler decryption still run. No diagnostic environment flag is needed. See the evaluation contract for authentication/key prerequisites.

Live requests use the configured provider's API key and await acceptance before returning the nonce. Acceptance is not handset delivery; failures omit the nonce, and timeouts must not trigger blind retries. The shared contract defines validation, HTTP outcomes and privacy-safe logging.

Source and extension points

Source Purpose
src/functions/SendOtp.js HTTP handler
src/functions/config.js Shared deployment settings
src/functions/models.js Delivery context, normalized ParsedResponse, and documented request objects
src/functions/dispatch.js Envelope/JWE handling, registry and dispatch
src/functions/providers/ Adapter manifests and API-specific implementations
test/ Representative offline checks

To add an adapter, implement manifest, buildRequest and parseResponse in the adapter folder and register it in src/functions/dispatch.js. Return a ParsedResponse from parseResponse; raw API-specific JSON stays inside that adapter. Keep credentials, options and status mapping with that adapter; the shared pipeline needs no provider-specific branches. See production limitations before production use.