8 Service APIs

This section provides a reference for APIs that should be implemented by this Building Block.

The APIs defined here establish a blueprint for how the Building Block will interact with other Building Blocks. Additional APIs may be implemented by the Building Block, but the listed APIs define a minimal set of functionality that should be provided by any implementation of this Building Block.

In common for all services of the Identity Building Block, the API expects the calling Partner has been already authenticated and authorized to access the service. For detailed specifications of APIs with input/output formats please refer to API specifications defined in YAML in the corresponding GitHub repository.

The GovStack non-functional requirements document provides additional information on how 'adaptors' may be used to translate an existing API to the patterns described here. This section also provides guidance on how candidate products are tested and how GovStack validates a product's API against the API specifications defined here.

The tests for the Identity Building Block can be found in this GitHub repository.

API standards

8.1 Identity Usage

The Identity usage APIs are a set of OpenAPI specifications exposed by the Identity Building Block to other building blocks and applications for user verification.

The Identity usage APIs are based on the following principles:

  • Verification APIs are inspired by OpenID Connect protocol which simplifies integrations using pre-existing libraries

  • Only secure options in OpenID connect should be supported to ensure the user data is handled securely

  • All biometric capture for user verification should be done using Secure Biometrics Interface standards

Service Group: Client Management

Create OIDC Client Endpoint

API to add new open ID connect (OIDC) clients, it can be invoked by other modules which manages the relying parties / partners.

Each relying party can associate to one or multiple OIDC client Ids.

On create, OIDC client status will be by default set to "active".

POST/client-mgmt/oidc-client
Authorization
Body
requestTime*string

Current date and time when the request is sent

request*object
Response

OK

Body
responseTimestring

Date and time when the response is generated

responseobject
errorsarray of object
Request
const response = await fetch('/client-mgmt/oidc-client', {
    method: 'POST',
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "2011-10-05T14:48:00.000Z",
      "request": {
        "clientId": "e-health-service",
        "clientName": "Health Service",
        "relyingPartyId": "bharath-gov",
        "logoUri": "http://example.com",
        "redirectUris": [
          "http://example.com/login-success"
        ],
        "publicKey": {},
        "authContextRefs": [
          "idbb:acr:generated-code"
        ],
        "userClaims": [
          "name"
        ],
        "grantTypes": [
          "authorization_code"
        ],
        "clientAuthMethods": [
          "private_key_jwt"
        ]
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "clientId": "text"
  },
  "errors": [
    {
      "errorCode": "duplicate_client_id",
      "errorMessage": "text"
    }
  ]
}

Update OIDC Client Endpoint

API to update existing Open ID Connect (OIDC) client, it can be invoked by other modules which manages the relying parties / partners when there any updates on the fields accepted in this API.

Authentication and authorization is based on a valid JWT issued by a trusted IAM system including "update_oidc_client" scope.

PUT/client-mgmt/oidc-client/{client_id}
Authorization
Path parameters
client_id*string

Client Identifier

Example: "785b806d0e594657b05aabdb30fff8a4"
Body
requestTime*string

Current date and time when the request is sent

request*object
Response

OK

Body
responseTimestring

Date and time when the response is generated

responseobject
errorsarray of object

List of Errors in case of request validation / processing failure in IDBB server. When request processing is fully successful, this array will be empty.

Request
const response = await fetch('/client-mgmt/oidc-client/{client_id}', {
    method: 'PUT',
    headers: {
      "Authorization": "Bearer <token>",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "2022-09-22T08:03:45.000Z",
      "request": {
        "clientName": "Health Service",
        "status": "active",
        "logoUri": "http://example.com",
        "redirectUris": [
          "http://example.com/login-success"
        ],
        "userClaims": [
          "name"
        ],
        "authContextRefs": [
          "idbb:acr:generated-code"
        ],
        "grantTypes": [
          "authorization_code"
        ],
        "clientAuthMethods": [
          "private_key_jwt"
        ]
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "clientId": "text"
  },
  "errors": [
    {
      "errorCode": "invalid_client_id",
      "errorMessage": "text"
    }
  ]
}

Authorization Endpoint

This is the authorize endpoint of Open ID Connect (OIDC). The relying party applications will do a browser redirect to this endpoint with all required details passed as query parameters.

This endpoint will respond with a HTML page / JS application to be loaded in the browser.

All the validations on the query parameter values will be performed, in case of any failures respective error message will be sent along with browser redirection back to relying party application.

GET/authorize
Query parameters
Response

OK

Loads IDBB UI application in browser for interacting with user for Login process

Request
const response = await fetch('/authorize?scope=openid+profile&response_type=code&client_id=text&redirect_uri=https%3A%2F%2Fexample.com', {
    method: 'GET',
    headers: {},
});
const data = await response.json();

Token Endpoint

Once the client / relying party application receives the authorization code through redirect, this OIDC complaint endpoint will be called from the relying party backend application to get the ID Token and Access Token.

  1. The only supported client authentication method : private_key_jwt
  2. ClientAssertion is a signed JWT with client's private key, corresponding public key should be shared with IDBB during the OIDC client creation process.
  3. clientAssertion JWT payload must be as below:

The JWT MUST contain the following REQUIRED Claim Values and MAY contain few additional OPTIONAL Claim Values:

iss* (Issuer): This MUST contain the client_id of the OIDC / OAuth Client.

sub* (Subject): This MUST contain the client_id of the OIDC / OAuth Client.

aud* (Audience): Value that identifies the IDBB server as an intended audience. The IDBB server MUST verify that it is an intended audience for the token. The audience SHOULD be the URL of the IDBB's token endpoint.

exp* (Expiration): Time on or after which the ID token MUST NOT be accepted for processing.

iat*: Time at which the JWT was issued.

Note: The Client Assertion JWT can contain other Claims. Any Claims used that are not understood WILL be ignored.

POST/oauth/token
Body
grant_type*enum

Authorization code grant type.

authorization_code
code*string

Authorization code, sent as query param in the client's redirect URI.

client_id*string

Client Id of the OIDC client.

client_assertion_type*enum

Type of the client assertion part of this request.

urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertion*string

Private key signed JWT, This JWT payload structure is defined above as part of request description.

redirect_uri*string

Valid client redirect_uri. Must be same as the one sent in the authorize call.

Response

OK

Headers
Body
id_token*string

Identity token in JWT format. Will have the below claims in the payload.

access_token*string

The access token in JWT format. This token will be used to call the UserInfo endpoint. Relying party application should handle access token as opaque.

token_type*enum

The type of the access token, set to Bearer

Bearer
expires_in*number (duration)

The lifetime of the access token, in seconds.

Request
const response = await fetch('/oauth/token', {
    method: 'POST',
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: JSON.stringify({
      "grant_type": "authorization_code",
      "code": "text",
      "client_id": "text",
      "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
      "client_assertion": "text",
      "redirect_uri": "text"
    }),
});
const data = await response.json();
Response
{
  "id_token": "text",
  "access_token": "text",
  "token_type": "Bearer",
  "expires_in": 0
}

UserInfo Endpoint

Once the access token is received via the token endpoint, relying party backend application can call this OIDC compliant endpoint to request for the user claims.

Consented user claims will be returned as a JWT. This JWT will be a nested JWT which is signed using JWS and then encrypted using JWE.

Example: Assuming the below are the requested claims by the relying party

name : { "essential" : true }

phone: { "essential" : true }

Response 1: When consent is provided for both name and phone number:

{ "name" : "John Doe", "phone" : "033456743" }

Response 2: When consent is provided for only name:

{ "name" : "John Doe" }

Response 3: When Claims are requested with claims_locales : "en fr"

{ "name#en" : "John Doe", "name#fr" : "Jean Doe", "phone" : "033456743" }

Supported User Info Claims

GET/oidc/userinfo
Authorization
Response

OK

Body
string (jwt)

The response is signed and then encrypted, with the result being a Nested JWT. Signed using the IDBB's private key. Signed full JWT will then be encrypted using OIDC client's public key.

Request
const response = await fetch('/oidc/userinfo', {
    method: 'GET',
    headers: {
      "Authorization": "Bearer <token>"
    },
});
const data = await response.json();
Response
text

JSON Web Key Set Endpoint

Endpoint to fetch all the public keys of the IDBB server. Returns public key set in the JWKS format.

GET/.well-known/jwks.json
Response

OK

Body
keysarray of object
Request
const response = await fetch('/.well-known/jwks.json', {
    method: 'GET',
    headers: {},
});
const data = await response.json();
Response
{
  "keys": [
    {
      "kid": "text",
      "use": "sig",
      "kty": "RSA",
      "e": "text",
      "n": "text",
      "x5t#S256": "text",
      "x5c": [
        "text"
      ],
      "exp": "2026-02-05T13:43:07.979Z"
    }
  ]
}

Configuration Endpoint

This endpoint is only for facilitating the OIDC provider details in a standard way.

Reference: https://openid.net/specs/openid-connect-discovery-1_0.html

GET/.well-known/openid-configuration
Response

OK

Body
issuer*string

URL using the https scheme with no query or fragment component that the RP asserts as its Issuer Identifier. This also MUST be identical to the iss Claim value in ID Tokens issued from this Issuer.

authorization_endpoint*string

URL of the OAuth 2.0 Authorization Endpoint.

token_endpoint*string

URL of the OAuth 2.0 Token Endpoint.

userinfo_endpoint*string

URL of the OP's UserInfo Endpoint.

jwks_uri*string

URL of the OP's JSON Web Key Set [JWK] document.

registration_endpoint*string

URL of Client Registration Endpoint.

scopes_supported*array of enum

JSON array containing a list of the OAuth 2.0 [RFC6749] scope values that this server supports.

response_types_supported*array of enum

JSON array containing a list of the OAuth 2.0 response_type values that this OP supports.

acr_values_supportedarray of any

JSON array containing a list of the Authentication Context Class References that IDP supports.

userinfo_signing_alg_values_supportedarray of any

JSON array containing a list of the JWS [JWS] signing algorithms.

userinfo_encryption_alg_values_supportedarray of any

JSON array containing a list of the JWE [JWE] encryption algorithms.

userinfo_encryption_enc_values_supportedarray of any

JSON array containing a list of the JWE encryption algorithms (enc values) [JWA] supported by the UserInfo Endpoint to encode the Claims in a JWT.

token_endpoint_auth_methods_supportedarray of enum

JSON array containing a list of Client Authentication methods supported by this Token Endpoint.

display_values_supportedarray of any

JSON array containing a list of the display parameter values that the OpenID Provider supports.

claim_types_supportedarray of enum

JSON array containing a list of the Claim Types that the OpenID Provider supports.

claims_supportedarray of string

JSON array containing a list of the Claim Names of the Claims that the OpenID Provider MAY be able to supply values for.

claims_locales_supportedarray of string

Languages and scripts supported for values in Claims being returned.

ui_locales_supportedarray of string

Languages and scripts supported for the user interface.

response_modes_supportedarray of enum

Mechanism to be used for returning parameters from the Authorization Endpoint.

token_endpoint_auth_signing_alg_values_supportedarray of enum
id_token_signing_alg_values_supportedarray of enum
Request
const response = await fetch('/.well-known/openid-configuration', {
    method: 'GET',
    headers: {},
});
const data = await response.json();
Response
{
  "issuer": "text",
  "authorization_endpoint": "text",
  "token_endpoint": "text",
  "userinfo_endpoint": "text",
  "jwks_uri": "text",
  "registration_endpoint": "text",
  "scopes_supported": [
    "openid"
  ],
  "response_types_supported": [
    "code"
  ],
  "acr_values_supported": [],
  "userinfo_signing_alg_values_supported": [],
  "userinfo_encryption_alg_values_supported": [],
  "userinfo_encryption_enc_values_supported": [],
  "token_endpoint_auth_methods_supported": [
    "private_key_jwt"
  ],
  "display_values_supported": [],
  "claim_types_supported": [
    "normal"
  ],
  "claims_supported": [
    "text"
  ],
  "claims_locales_supported": [
    "text"
  ],
  "ui_locales_supported": [
    "text"
  ],
  "response_modes_supported": [
    "query"
  ],
  "token_endpoint_auth_signing_alg_values_supported": [
    "RS256"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ]
}

For Identity Building Block implementations that support mobile wallet integration, the following API spec should also be implemented.

Generate link code request is raised from IDBB UI application.

  1. UI application creates a deeplink with this link-code as parameter.
  2. This deeplink is embedded in a Machine-readable-code (like QR code) and the same is rendered in the UI.
  3. End user scans this machine-readable-code to open wallet app.
  4. On open of wallet-app, wallet-app invokes /link-transaction endpoint.
  5. In the UI application, once machine-readable-code is rendered, at the same time /link-status endpoint is invoked as a long polling request.
POST/linked-authorization/link-code
Header parameters
Body
requestTime*string
request*object
Response

OK

Body
responseTimestring
responseobject
errorsarray of object
Request
const response = await fetch('/linked-authorization/link-code', {
    method: 'POST',
    headers: {
      "X-XSRF-TOKEN": "text",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "text",
      "request": {
        "transactionId": "text"
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "transactionId": "text",
    "linkCode": "text",
    "expireDateTime": "text"
  },
  "errors": [
    {
      "errorCode": "invalid_transaction_id",
      "errorMessage": "text"
    }
  ]
}

The link status endpoint is invoked from IDBB UI application.

  1. Checks the status of link code and will return the status as LINKED once the /link-transaction endpoint is called from wallet application.
POST/linked-authorization/link-status
Header parameters
Body
requestTime*string
request*object
Response

OK

Body
responseTImestring
responseobject
errorsarray of object
Request
const response = await fetch('/linked-authorization/link-status', {
    method: 'POST',
    headers: {
      "X-XSRF-TOKEN": "text",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "text",
      "request": {
        "transactionId": "text",
        "linkCode": "text"
      }
    }),
});
const data = await response.json();
Response
{
  "responseTIme": "text",
  "response": {
    "transactionId": "text",
    "linkStatus": "LINKED",
    "linkedDateTime": "text"
  },
  "errors": [
    {
      "errorCode": "invalid_transaction_id",
      "errorMessage": "text"
    }
  ]
}

Link authorization code endpoint is invoked from UI application.

  1. This is a Long polling request to IDBB backend.
  2. validates the transactionId
  3. validates the linkCode if its LINKED.
  4. checks the cache to see if the auth-code is generated, if yes returns the response.
  5. If the auth-code is not yet generated, polling request waits for the configured time.
  6. On successful response, IDBB UI should redirect to the provided redirectUri with auth-code or error details.
POST/linked-authorization/link-auth-code
Header parameters
Body
requestTime*string
request*object
Response

OK

Body
responseTimestring
responseobject
errorsarray
Request
const response = await fetch('/linked-authorization/link-auth-code', {
    method: 'POST',
    headers: {
      "X-XSRF-TOKEN": "text",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "text",
      "request": {
        "transactionId": "text",
        "linkedCode": "text"
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "code": "text",
    "redirectUri": "text",
    "state": "text",
    "nonce": "text"
  }
}

The link transaction endpoint is invoked from Wallet-app.

  1. Validates the link-code and its expiry and generates the linkTransactionId. This linkTransactionId is linked to transactionId used in the /link-code endpoint.

  2. Returns the auth-factors, clientName, logoUrl, User claims, authorize scopes along with linkTransactionId.

Note: Wallet-app will hereafter address the transaction with this linkTransactionId for the /authenticate and /consent endpoints.

POST/linked-authorization/link-transaction
Body
requestTime*string
request*object
Response

OK

Body
responseTimestring
responseobject
errorsarray of object
Request
const response = await fetch('/linked-authorization/link-transaction', {
    method: 'POST',
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "text",
      "request": {
        "linkCode": "text"
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "linkTransactionId": "text",
    "clientName": "text",
    "logoUrl": "text",
    "authorizeScopes": [
      "text"
    ],
    "essentialClaims": [
      "text"
    ],
    "voluntaryClaims": [
      "text"
    ],
    "authFactors": [
      [
        {
          "type": "PIN",
          "bioSubTypes": [
            "text"
          ]
        }
      ]
    ]
  },
  "errors": [
    {
      "errorCode": "invalid_link_code",
      "errorMessage": "text"
    }
  ]
}

Linked Authentication Endpoint

Once end user provides the user identifier (UIN/VID) and all the required auth challenge to the Wallet-app, this endpoint will be invoked from wallet-app.

Supported auth-challenge depends on the integrated IDBB implementation.

  1. Validates linkedTransactionId.
  2. Validates null / empty individualId.

On Authentication Success: Only linkTransactionId is returned in the below response without any errors.

On Authentication Failure: Error list will be returned.

POST/linked-authorization/authenticate
Body
requestTime*string
Pattern: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
request*object
Response

OK

Body
responseTimestring
responseobject
errorsarray of object

List of Errors in case of request validation / processing failure in IDBB server.

Request
const response = await fetch('/linked-authorization/authenticate', {
    method: 'POST',
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "text",
      "request": {
        "linkedTransactionId": "text",
        "individualId": "text",
        "challengeList": [
          {
            "authFactorType": "OTP",
            "challenge": "text",
            "format": "alpha-numeric"
          }
        ]
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "linkedTransactionId": "text"
  },
  "errors": [
    {
      "errorCode": "invalid_transaction_id",
      "errorMessage": "text"
    }
  ]
}

Once the authentication is successful and user permission is obtained, this endpoint will be invoked by the wallet app to send the accepted user claims and permitted scopes.

  1. Validates linkedTransactionId.
  2. Validate accepted claims and permitted scopes in the request.
  3. If valid, stores the accepted claims and permitted scopes in the datastore.
POST/linked-authorization/consent
Body
requestTime*string
Pattern: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
request*object
Response

OK

Body
responseTimestring
responseobject
errorsarray of object
Request
const response = await fetch('/linked-authorization/consent', {
    method: 'POST',
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "text",
      "request": {
        "linkedTransactionId": "text"
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "linkedTransactionId": "text"
  },
  "errors": [
    {
      "errorCode": "invalid_transaction_id",
      "errorMessage": "text"
    }
  ]
}

Wallet Binding Endpoint (Draft)

Wallet binding endpoint is invoked by Wallet's backend server.

  1. Action will be initiated from wallet-app with authChallenge by user.
  2. Wallet backend server will receive the authChallenge, create this request and send to IDBB to complete the binding process.
  3. Binded walletUserId (WUID) is returned with IDBB signed certificate.

Note: Binding entry uniqueness is combination of these 3 values -> (PSUT, public-key, auth-factor-type)

POST/wallet-binding
Authorization
Header parameters
Body
requestTime*string
request*object
Response

OK

Body
responseTime*string
responseobject
errorsarray of object
Request
const response = await fetch('/wallet-binding', {
    method: 'POST',
    headers: {
      "Authorization": "Bearer <token>",
      "PARTNER-ID": "text",
      "PARTNER-API-KEY": "text",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      "requestTime": "text",
      "request": {
        "individualId": "text",
        "authFactorType": "text",
        "format": "text",
        "challengeList": [
          {
            "authFactorType": "OTP",
            "challenge": "text",
            "format": "alpha-numeric"
          }
        ]
      }
    }),
});
const data = await response.json();
Response
{
  "responseTime": "text",
  "response": {
    "walletUserId": "text",
    "certificate": "text",
    "expireDateTime": "text"
  },
  "errors": [
    {
      "errorCode": "unsupported_challenge_format",
      "errorMessage": "text"
    }
  ]
}

Detailed API schemas written in YAML that define REST API endpoints for each of the services mentioned above are available on GitHub located at the Identity-Provider YAML.

The GovStack non-functional requirements document provides additional information on how 'adaptors' may be used to translate an existing API to the patterns described here.

8.2 Identity Management

The Enrollment APIs are a set of OpenAPI specifications exposed by the Identity Building Block ‘Enrollment Server’ service to any enrollment client.

The Enrollment APIs are based on the following principles:

  • When enrollment is done in one step, the CreateEnrollment can contain all the data and an additional flag (finalize) to indicate all data was collected.

  • During the process, the enrollment structure can be updated. Only the data that changed need to be transferred. Data not included is left unchanged on the server. In the following example, the biographic data is not changed.

  • Images can be passed by value or reference.

  • Existing standards are used whenever possible, for instance, the preferred image format for biometric data is ISO-19794. The underlying data should be of open mime types that offer good compression without loss of data (for example JPEG2000 for images).

8.3 Credential Management

These Credential Management APIs are a set of OpenAPI specifications exposed by the Identity Building Block to service identity credential requests by credential partners such as printing and QR code partners.

The Credential Management APIs are based on the following principles:

  • The credential request API is asynchronous for the identity holder i.e., the call to share credentials is responded with an event ID. Then the identity holder later uses the event ID to retrieve the details using the API '/events/{eventId}'.

  • The '/share-credential' API is used to convey the format of the credential information. The format allows the credential information to be masked/unmasked. The API also conveys the consent of the identity holder.

  • The API '/download/personalized-card' is used to download the identity card in PDF format.

  • Systems for Voter ID, Tax ID, Card printing etc. receive internal notifications from IDBB.

  • Wallet applications will receive the identity credentials as per pre-authorized flow.

  • The APIs '/block', '/unblock' and '/updateIdentity' can only be called by systems with administrative permissions given by the IDBB.

8.4 Subscription Management

The Subscription Management APIs follow the APIs from these standards - WebSub and WebHooks.

8.5 Administration Management

This Services APIs is not yet specified, but it should be the purpose of a next iteration of the Identity Building Block Specification.

Last updated

Copyright © 2024