Kulcare Docs

ABDM Webhook Gateway Token Settings

ABDM gateway callbacks (/integration/abdm/webhooks/* and /integration/abdm/api/v3/*) carry an RS256 bearer token from the gateway. Integration::Abdm::WebhookAuthenticator verifies its signature, and can also check its issuer, its audience and a claim that names the HIP or HIU. Those last three need values taken from a real sandbox gateway token. The repo has no captured token, so they are not set yet. This page lists them so the ABDM integration owner can fill them in (#2416).

What is enforced today

CheckWhereWithout the setting
RS256 signature against the gateway JWKS (jwks_url)authenticatoralways on
Issuer (iss)authenticatoroff. Production refuses to boot; staging boots and logs a warning
Audience (aud)authenticatoroff. When set, a token with no aud still passes
Token service-id claim equals X-HIP-ID / X-HIU-IDcontrollerchecked only when the token has the claim
Token must have the service-id claimauthenticatoroff (abdm_require_service_id_claim is false)
Body HIP/HIU id equals the headercontrolleralways on, where the body has the field (table below)

While abdm_require_service_id_claim is off, a token with no service-id claim still takes its tenant from the unsigned X-HIP-ID / X-HIU-ID header. The body check narrows that, but the body is not signed either. Turning the setting on is what closes #2416.

Settings that need a captured token

Each setting is read from the env var first, then from Rails credentials (top-level key, not nested).

SettingEnv varCredential keyWhat to take from the token
Expected issuerABDM_JWT_EXPECTED_ISSabdm_jwt_expected_issThe exact iss value. Sandbox and production differ, so set it per environment
Expected audienceABDM_JWT_EXPECTED_AUDabdm_jwt_expected_audThe aud value, if the token has one. Leave unset if it has none
Service-id claim pathABDM_SERVICE_ID_CLAIMabdm_service_id_claim_pathThe dotted path of the claim whose value is our HIP/HIU id (for example a.b). Defaults to service_id, which is a guess, not a known ABDM claim
Require the claimABDM_REQUIRE_SERVICE_ID_CLAIMabdm_require_service_id_claimSet true only after the path above is confirmed on both a HIP and an HIU callback

How to capture a token

  1. On staging, let a sandbox callback arrive (for example a discover from the PHR app, or a consent notify). The Authorization header is redacted in abdm_callbacks.headers, so capture it at the edge (load balancer or a temporary log line) and remove the capture afterwards.
  2. Decode the token's payload (the middle segment, base64url). Do not paste the token anywhere public: it is a live gateway credential until it expires.
  3. Note iss, aud (if any), and any claim whose value equals the X-HIP-ID or X-HIU-ID header of that same request.
  4. Repeat for an HIU callback (X-HIU-ID) and confirm the same claim path holds the HIU id.
  5. Set the values above on staging, run the manual test plan in #2416, then set them in production.

Body fields checked against the header

Webhook controllerActionBody field
hip_link_webhooksprofile_sharemetaData.hipId
hip_link_webhookstoken, add-contexts, auth, context and SMS notify, running token statusnone
hip_consent_webhooksconsent_notifynotification.consentDetail.hip.id
hip_data_webhookson_requestnone (consent id only)
hip_discovery_webhooksdiscoverhip.id or hipId (older shapes; the v3 body has neither)
hip_discovery_webhookslink_init, link_confirmnone
hiu_consent_webhookson_fetchconsent.consentDetail.hiu.id
hiu_consent_webhooksconsent_notify, on_init, on_statusnone
hiu_data_webhooksdata_notification, on_requestnone (statusNotification.hipId names the sending HIP, not us)

A body without the field passes. A body whose field names a different service than the header gets 401. Fields come from the ABDM v3 specs in docs/abdm/specs/.

On this page