Developer Reference

Authentication Dev — Integration Guide

This document describes the Authentication Dev module in kasookoo-sdk-backend: what it does, how it is implemented, and how to integrate it from client apps.

It is based on the Kasookoo Authentication Dev Technical Brief (June 2026, v1.0) and maps each recommended architecture option to concrete services and SIP/WhatsApp integration hooks in this repository.

Non-technical overview: AUTHENTICATION USE CASE

API details: Authentication API Reference


Table of contents

  1. Overview
  2. Verification options
  3. Architecture in this backend
  4. Authentication
  5. Configuration
  6. Prerequisites
  7. End-to-end flows
  8. SIP / WhatsApp integration
  9. Security
  10. Testing checklist
  11. Limitations

Overview

Authentication Dev uses a phone call as the verification signal instead of SMS OTP.

Under Nigerian telco rules, outbound calls use a fixed CLI (a single DID). Kasookoo cannot encode a per-session OTP in the caller ID. This module supports multiple verification architectures:

OptionMethod valueSummary
1 — PSTN Call-back (recommended)callbackUser on a mobile dials Kasookoo's fixed DID over GSM/PSTN; verification uses the mobile's MSISDN
2 — WhatsApp Call-backcallback_whatsappUser on a mobile with WhatsApp places an inbound WhatsApp voice call; verification uses the WhatsApp caller ID mapped to MSISDN
3 — Flashcallmissed_outbound_callBrief outbound ring from fixed CLI; SDK detects missed call and verifies with device_fingerprint + session_id binding
4 — Enhanced OTP Callvoice_otpOutbound call + IVR reads OTP; OTP also delivered to App via push; user consents and verifies with one button
5 — InApppush_otpPush delivers verification code to SDK; App shows OTP on screen with consent; user verifies with one button

Verification options

Option 1 — PSTN Call-back (callback)

Requirement: The user must complete verification from a mobile phone capable of placing a GSM/PSTN call via the native dialler (cellular network). Desktop, tablet-only, or in-app VoIP dialling are not supported for this option.

  1. App starts verification via SDK; SDK creates a session tied to the user's MSISDN (60 s TTL by default).
  2. SDK returns session_id, did_number, and expires_at to App.
  3. App instructs the user to dial did_number from their mobile using the GSM/PSTN phone app (not from the integrating app).
  4. The SIP server receives the inbound PSTN call from the mobile and forwards call metadata to the verification agent.
  5. The verification agent checks caller ID (ANI/MSISDN) and validates an active pending session for the same org and MSISDN.
  6. If checks pass, the agent marks the session verified and tears down the call before full connect completes.
  7. SDK/App receives verification status via push notification.

Option 2 — WhatsApp Call-back (callback_whatsapp)

Requirement: The user must complete verification from a mobile phone with WhatsApp installed and able to place an inbound WhatsApp voice call. WhatsApp Web/desktop-only clients are not supported for this option.

  1. App starts verification via SDK; SDK creates a session with method=callback_whatsapp.
  2. SDK returns session_id, whatsapp_number, and expires_at to App.
  3. App instructs the user to call whatsapp_number from their mobile WhatsApp app (voice call, not chat message).
  4. WhatsApp Business API receives the inbound voice call from the mobile and forwards caller metadata to the verification agent.
  5. The verification agent maps WhatsApp caller ID (wa_id) to normalized MSISDN and validates an active pending session for the same org and MSISDN.
  6. If checks pass, the agent marks the session verified and tears down the call before full connect completes.
  7. SDK/App receives verification status via push notification.

Option 3 — Flashcall (missed_outbound_call)


Note: The API accepts method: hybrid and method: outbound_missed_call as legacy aliases for missed_outbound_call.

  1. App starts verification via SDK; SDK creates a session with method=missed_outbound_call and device_fingerprint.
  2. SDK returns session_id, fixed_cli, and expires_at to App.
  3. SDK calls POST /sessions/{id}/trigger-outbound — SIP server rings the user from fixed_cli, then disconnects after the configured ring duration.
  4. SDK detects the missed call from fixed_cli on the user's handset.
  5. SDK calls POST /sessions/{id}/verify with matching device_fingerprint.
  6. SDK returns verification status to App.

Option 4 — Enhanced OTP Call (voice_otp)

  1. App starts verification via SDK; SDK creates a session with method=voice_otp.
  2. SDK returns session_id, fixed_cli, and expires_at to App.
  3. SDK calls POST /sessions/{id}/trigger-outbound — SIP server places an outbound call and sends the same OTP to SDK via push notification.
  4. User answers the call; the voice agent reads OTP digits via IVR/TTS
  5. Push notification service delivers OTP to SDK; App shows consent screen (user agrees to hear audio and view OTP on screen).
  6. User taps a single Verify button; SDK auto-submits the OTP from the push payload via POST /sessions/{id}/verify-otp.
  7. SDK returns verification status to App.

Option 5 — InApp (push_otp)

  1. App starts verification via SDK; SDK creates a session with method=push_otp and device_fingerprint.

  2. SDK returns session_id and expires_at to App.

  3. SDK calls POST /sessions/{id}/trigger-outbound — backend sends a push notification with the verification code to SDK.

  4. Push notification service delivers OTP to SDK; App shows consent screen with OTP on screen.

  5. User taps a single Verify button; SDK auto-submits the code from the push payload via POST /sessions/{id}/verify.

  6. SDK returns verification status to App.

    >


Architecture in this backend

LayerFileResponsibility
Configapp/config.pySILENT_AUTH_CALL_* environment settings
Modelsapp/models/silent_auth_call_models.pyRequest/response Pydantic models
Serviceapp/services/silent_auth_call_service.pySession lifecycle, validation, SIP outbound, webhooks
APIapp/api/silent_auth_call.pyREST endpoints under /api/v1/silent-auth-call
SIP hookapp/services/redis/webhook_pipeline.pyInbound SIP/PSTN callback on participant_joined
Wiringapp/main.pyRouter mounted at /api/v1
Singletonapp/services/__init__.pysilent_auth_call_service instance

All public routes:

/api/v1/silent-auth-call/...
flowchart TB
    subgraph Client
        App[Mobile / Web App]
        SDK[Kasookoo SDK]
    end

    subgraph Backend["kasookoo-sdk-backend"]
        API[silent_auth_call.py]
        SVC[SilentAuthCallService]
        DB[(silent_auth_call_sessions)]
        WH[webhook_pipeline.py]
        PN[Push Notification Service]
    end

    subgraph Telephony
        SIP[SIP server]
        WA[WhatsApp Business API]
        DID[Fixed DID - inbound]
        CLI[Fixed CLI - outbound]
    end

    App --> SDK
    SDK -->|Bearer SDK JWT| API
    API --> SVC
    SVC --> DB
    SVC --> SIP
    SVC --> PN
    SIP --> WH
    WA --> WH
    WH --> SVC
    PN --> SDK
    SDK --> App
    UserCall[User MSISDN] --> DID --> SIP
    SIP --> CLI --> UserCall
    UserCall --> WA

Authentication

All Authentication Dev endpoints require a valid SDK JWT (Authorization: Bearer <sdk_access_token>).

See AUTHENTICATION_DEV_API.md for token minting, tenant scope, request/response schemas, and HTTP error codes.


Configuration

Set these in .env.local or Docker .env:

VariableDefaultDescription
SILENT_AUTH_CALL_DID_NUMBER(empty)Inbound DID fallback for Option 1 (PSTN)
SILENT_AUTH_CALL_FIXED_CLICALLER_ID fallbackOutbound caller ID fallback for Options 3 & 4
SILENT_AUTH_CALL_SESSION_TTL_SECONDS60Session lifetime
SILENT_AUTH_CALL_RATE_LIMIT_ATTEMPTS5Max session creations per MSISDN per window
SILENT_AUTH_CALL_RATE_LIMIT_WINDOW_MINUTES10Rate-limit window
SILENT_AUTH_CALL_OUTBOUND_RING_SECONDS3Flashcall ring duration before hangup
SILENT_AUTH_CALL_VOICE_OTP_LENGTH4OTP digit length (clamped 4–6)
MASTER_ORGANIZATION_ID(empty)Fallback org when JWT org resolution is unavailable internally

Line resolution order: org's primary associated number (is_primary=true) → env vars above.

Example:

SILENT_AUTH_CALL_DID_NUMBER=+2348012345678
SILENT_AUTH_CALL_FIXED_CLI=+2348012345678
SILENT_AUTH_CALL_SESSION_TTL_SECONDS=60
SILENT_AUTH_CALL_OUTBOUND_RING_SECONDS=3

Prerequisites

  1. SDK JWT — run Authentication → Create Client Session in Postman or your app auth flow.
  2. Primary associated number — create via POST /api/v1/associated-numbers with "is_primary": true for the org's inbound/outbound line.
  3. SIP webhooks — must reach the SDK backend ingest path for Option 1 (PSTN) inbound callback.
  4. User mobile (Option 1) — GSM/PSTN-capable handset; user dials did_number from the native phone app.
  5. WhatsApp Business API — inbound call webhooks configured for Option 2 (WhatsApp call-back).
  6. User mobile (Option 2) — WhatsApp installed; user places a voice call from the WhatsApp mobile app.
  7. Outbound SIP trunk — org trunk or SDK_SIP_OUTBOUND_TRUNK_ID for Options 3 & 4.
  8. Push notification service — configured for Options 1, 2, 4, and 5 (verification status or OTP delivery).

End-to-end flows

Option 1 — PSTN Call-back

sequenceDiagram
    participant App
    participant SDK
    participant API as Authentication Dev API
    participant DB as DB
    participant PN as Push Notification Service
    participant Mobile as User mobile (GSM)
    participant SIP as SIP server
    participant WH as webhook_pipeline

    App->>SDK: Start callback verification
    SDK->>API: POST /sessions (Bearer JWT, method=callback)
    API->>DB: insert pending session
    API-->>SDK: session_id, did_number, expires_at
    SDK-->>App: session_id, did_number, expires_at

    App->>Mobile: "Dial {did_number} from your mobile"
    Mobile->>SIP: Inbound GSM/PSTN call from MSISDN
    SIP->>WH: participant_joined (SIP metadata)
    WH->>API: handle_inbound_callback
    API->>DB: resolve pending session by org + MSISDN
    API->>DB: validate session is pending and unexpired
    API->>DB: set status=verified
    API->>SIP: hang up room
    API->>PN: send verification status
    PN-->>SDK: push notification (session verified)
    SDK-->>App: verification status=verified

Steps:

  • App asks SDK to start callback verification.
  • SDK calls POST /sessions with method=callback and creates a pending session in DB.
  • SDK returns session_id, did_number, and expires_at to App.
  • User mobile places an inbound GSM/PSTN call to did_number from the native dialler.
  • SIP server sends participant_joined metadata to webhook_pipeline.
  • API resolves the pending session by org + MSISDN, validates TTL/status, and marks it verified.
  • API hangs up the SIP call.
  • Push notification service sends verified status to SDK.
  • SDK notifies App that verification is complete.

Option 2 — WhatsApp Call-back

sequenceDiagram
    participant App
    participant SDK
    participant API as Authentication Dev API
    participant DB as DB
    participant WA as WhatsApp Business API
    participant PN as Push Notification Service
    participant Mobile as User mobile (WhatsApp)
    participant WH as webhook_pipeline

    App->>SDK: Start WhatsApp callback verification
    SDK->>API: POST /sessions (Bearer JWT, method=callback_whatsapp)
    API->>DB: insert pending session
    API-->>SDK: session_id, whatsapp_number, expires_at
    SDK-->>App: session_id, whatsapp_number, expires_at

    App->>Mobile: "Call {whatsapp_number} on WhatsApp"
    Mobile->>WA: Inbound WhatsApp voice call from same number
    WA->>WH: inbound_call webhook (wa_id metadata)
    WH->>API: handle_whatsapp_callback
    API->>DB: resolve pending session by org + mapped wa_id/MSISDN
    API->>DB: validate session is pending and unexpired
    API->>DB: set status=verified
    API->>WA: hang up call
    API->>PN: send verification status
    PN-->>SDK: push notification (session verified)
    SDK-->>App: verification status=verified

Steps:

  • App asks SDK to start WhatsApp callback verification.
  • SDK calls POST /sessions with method=callback_whatsapp and creates a pending session in DB.
  • SDK returns session_id, whatsapp_number, and expires_at to App.
  • User mobile places an inbound WhatsApp voice call to whatsapp_number.
  • WhatsApp Business API sends inbound_call webhook (wa_id metadata) to webhook_pipeline.
  • API maps wa_id to MSISDN, resolves pending session, validates TTL/status, and marks it verified.
  • API hangs up the WhatsApp call.
  • Push notification service sends verified status to SDK.
  • SDK notifies App that verification is complete.

Option 3 — Flashcall

sequenceDiagram
    participant App
    participant SDK
    participant API as Authentication Dev API
    participant DB as DB
    participant SIP as SIP server
    participant User

    App->>SDK: Start Flashcall verification
    SDK->>API: POST /sessions (Bearer JWT, method=missed_outbound_call, device_fingerprint)
    API->>DB: insert pending session
    API-->>SDK: session_id, fixed_cli, expires_at
    SDK-->>App: session_id, fixed_cli, expires_at

    SDK->>API: POST /sessions/{id}/trigger-outbound
    API->>DB: store outbound_room_name
    API->>SIP: outbound call to MSISDN (caller ID = fixed_cli)
    SIP->>User: ring from fixed_cli (~3s)
    API->>SIP: hang up after ring duration
    User->>SDK: missed call detected (fixed_cli match)

    SDK->>API: POST /sessions/{id}/verify (device_fingerprint)
    API->>DB: validate pending session + device_fingerprint
    API->>DB: set status=verified
    API-->>SDK: verified=true, msisdn
    SDK-->>App: verification status=verified

Steps:

  • App asks SDK to start Flashcall verification.
  • SDK calls POST /sessions with method=missed_outbound_call and device_fingerprint; API inserts pending session in DB.
  • SDK returns session_id, fixed_cli, and expires_at to App.
  • SDK calls POST /sessions/{id}/trigger-outbound.
  • API stores outbound_room_name and places outbound call via SIP server (caller ID = fixed_cli).
  • User handset rings briefly (~3s); API hangs up to create a missed-call signal.
  • SDK detects missed call from fixed_cli on the device.
  • SDK calls POST /sessions/{id}/verify with matching device_fingerprint.
  • API validates session + fingerprint, sets verified, and returns result to SDK.
  • SDK notifies App that verification is complete.

Option 4 — Enhanced OTP Call

sequenceDiagram
    participant App
    participant SDK
    participant API as Authentication Dev API
    participant DB as DB
    participant SIP as SIP server
    participant Agent as Voice Agent
    participant PN as Push Notification Service
    participant User

    App->>SDK: Start Enhanced OTP Call verification
    SDK->>API: POST /sessions (Bearer JWT, method=voice_otp)
    API->>DB: insert pending session + generate otp_code
    API-->>SDK: session_id, fixed_cli, expires_at
    SDK-->>App: session_id, fixed_cli, expires_at

    SDK->>API: POST /sessions/{id}/trigger-outbound
    API->>DB: store outbound_room_name
    API->>SIP: outbound call to MSISDN (caller ID = fixed_cli)
    API->>PN: send OTP to SDK (session_id + otp)
    SIP->>User: ring from fixed_cli
    User->>SIP: answer call
    SIP->>Agent: connect answered call
    Agent->>User: IVR/TTS reads OTP digits
    PN-->>SDK: push notification (OTP for on-screen display)
    SDK-->>App: show consent UI (listen audio + OTP on screen)

    User->>App: tap Verify (one button)
    App->>SDK: confirm verification
    SDK->>API: POST /sessions/{id}/verify-otp (otp from push payload)
    API->>DB: validate pending session + otp_code
    API->>DB: set status=verified
    API->>SIP: hang up call
    API-->>SDK: verified=true, msisdn
    SDK-->>App: verification status=verified

Steps:

  • App asks SDK to start Enhanced OTP Call verification.
  • SDK calls POST /sessions with method=voice_otp; API inserts pending session and generates otp_code in DB.
  • SDK returns session_id, fixed_cli, and expires_at to App.
  • SDK calls POST /sessions/{id}/trigger-outbound.
  • API places outbound call via SIP server and sends OTP to SDK through the push notification service.
  • User answers; voice agent reads OTP digits via IVR/TTS on the call.
  • SDK receives push with OTP; App shows consent UI (user agrees to hear audio and view OTP on screen).
  • User taps Verify once; SDK auto-submits OTP from push payload via POST /sessions/{id}/verify-otp.
  • API validates session + OTP, sets verified, and hangs up the call.
  • SDK notifies App that verification is complete.

Option 5 — InApp

sequenceDiagram
    participant App
    participant SDK
    participant API as Authentication Dev API
    participant DB as DB
    participant PN as Push Notification Service
    participant User

    App->>SDK: Start InApp verification
    SDK->>API: POST /sessions (Bearer JWT, method=push_otp, device_fingerprint)
    API->>DB: insert pending session + generate push_code
    API-->>SDK: session_id, expires_at
    SDK-->>App: session_id, expires_at

    SDK->>API: POST /sessions/{id}/trigger-outbound
    API->>DB: resolve user by msisdn + org
    API->>DB: read active push tokens
    API->>PN: send push (session_id + verification code)
    PN-->>SDK: push notification (OTP for on-screen display)
    SDK-->>App: show consent UI (OTP on screen)

    User->>App: tap Verify (one button)
    App->>SDK: confirm verification
    SDK->>API: POST /sessions/{id}/verify (device_fingerprint, code from push payload)
    API->>DB: validate pending session + fingerprint + push_code
    API->>DB: set status=verified
    API-->>SDK: verified=true, msisdn
    SDK-->>App: verification status=verified

Steps:

  • App asks SDK to start InApp verification.
  • SDK calls POST /sessions with method=push_otp and device_fingerprint; API inserts pending session and generates push_code in DB.
  • SDK returns session_id and expires_at to App.
  • SDK calls POST /sessions/{id}/trigger-outbound.
  • API resolves user by MSISDN + org, reads active push tokens, and sends push with verification code.
  • Push notification service delivers OTP to SDK; App shows consent UI with OTP on screen.
  • User taps Verify once; SDK auto-submits code from push payload via POST /sessions/{id}/verify.
  • API validates session + fingerprint + code, sets verified, and returns result to SDK.
  • SDK notifies App that verification is complete.

SIP / WhatsApp integration

Inbound PSTN callback (Option 1)

Hook: app/services/redis/webhook_pipeline.py → handle_silent_auth_call_inbound_from_webhook

Runs on SIP participant_joined webhook events when the participant is SIP and the called DID matches the org's primary associated number (or env fallback). The user must originate the call from a GSM/PSTN mobile via the native dialler. For PSTN inbound calls, verification is handled in the agent path: caller ID is extracted from SIP metadata, matched to a pending session, and only then the session is marked verified. This runs before normal SIP inbound user mapping so Authentication Dev takes precedence on the auth DID.

WhatsApp callback (Option 2)

Inbound WhatsApp voice call webhook events should provide caller metadata (wa_id) from the user's WhatsApp mobile app. WhatsApp Web/desktop clients are not valid origins. Verification logic should resolve a matching pending session, mark it verified, tear down the call, then notify SDK/App via push.

Flashcall (Option 3)

SilentAuthCallService.trigger_outbound() creates an outbound session room and places the call through the SIP server using the org trunk (or SDK_SIP_OUTBOUND_TRUNK_ID fallback). The call rings briefly from fixed_cli, then the SIP server disconnects to produce a missed-call signal on the user's handset. The SDK then calls POST /sessions/{id}/verify with device_fingerprint.

Enhanced OTP Call (Option 4)

Uses the same SIP outbound path as Option 3, but the user answers the call. A voice agent reads the server-generated OTP via IVR/TTS. In parallel, the backend sends the same OTP to SDK through the push notification service so App can display it on screen. App shows a consent prompt (listen to audio + view OTP), then the user confirms with a single Verify button; SDK auto-submits POST /sessions/{id}/verify-otp with the OTP from the push payload.

InApp (Option 5)

POST /sessions/{id}/trigger-outbound resolves the user by MSISDN, reads active push tokens, and sends a verification code via the push notification service to SDK. App displays the OTP on a consent screen; the user confirms with a single Verify button and SDK auto-submits POST /sessions/{id}/verify with the code from the push payload. No SIP call is placed.


Security

ControlImplementation
AuthenticationSDK JWT on all endpoints
Tenant isolationOrg from JWT; session routes return 404 for wrong org
Session TTLDefault 60 s; expired pending sessions auto-marked expired
Rate limitingMax session creations per MSISDN per window
Flashcall replay protectiondevice_fingerprint required at create for missed_outbound_call; mismatch → 403
InApp replay protectiondevice_fingerprint + code required for push_otp; mismatch → 403
OTP secrecyotp_code never returned; compared with secrets.compare_digest
HTTPS onlywebhook_url must start with https://

Testing checklist

Use the Authentication Dev folder in Kasookoo_SDK_Backend_Complete.postman_collection.json.

  1. Run Authentication → Create Client Session (SDK JWT).
  2. Create an associated number with "is_primary": true.
  3. GET /silent-auth-call/health → configured: true.
  4. Option 1: Create callback session → user dials DID from mobile GSM/PSTN dialler → verify via push notification.
  5. Option 2: Create callback_whatsapp session → user places WhatsApp voice call from mobile → verify via push notification.
  6. Option 3: Create missed_outbound_call session → trigger outbound → SDK detects missed call → verify with fingerprint.
  7. Option 4: Create voice_otp session → trigger outbound → receive OTP push → consent screen → one-button verify.
  8. Option 5: Create push_otp session → trigger outbound → receive OTP push → consent screen → one-button verify.

Limitations

ItemStatus
Option 1 PSTN inbound callback via SIP webhook (GSM mobile dialler)Implemented
Option 2 WhatsApp callback via inbound voice call webhook (WhatsApp mobile app)Design documented — implementation pending
VoIP / in-app dialler origination on Option 1Not supported — GSM/PSTN mobile dialler required
WhatsApp Web / desktop origination on Option 2Not supported — WhatsApp mobile voice call required
Option 3 Flashcall + SDK verifyImplemented
Option 4 Enhanced OTP Call + one-button verifyDesign documented — push OTP delivery and consent UI pending
Option 4 IVR/TTS OTP read-out on answered callNot implemented — requires voice agent integration
Option 5 InApp + one-button verifyDesign documented — consent UI pending; code submit via push payload
VoIP origination detection on inbound MSISDNNot implemented — prefix validation only

Related documentation


Kasookoo Communications Ltd · Kasookoo SDK Backend


Did this page help you?