# Set up to be Service Provider

🔗 Registration

🔗 SDK installation

Let's upgrade your role to be Service Provider on serviceX Dashboard.

image

In this process, the following information is required.

  • Redirection URLs
    • The URLs that will be used once users complete OpenID Connect flow.
  • Logout URLs
    • The URLs that will be used when users log out.
  • OIDC setup URL
    • The URL required to kick off OpenID Connect with Credify. This may generate an ephemeral encryption key to securely deal with claims.
  • User existence API endpoint
    • This is an API to return whether a specified user exists in this Service Provider's system or not. If it's idX integration, this is not needed.
  • Scopes
    • Scopes list that will be required to be shared by users.

What to do here is quite similar to the idX usage (Credify Login).

# OIDC setup URL - Backend

Credify's OpenID Connect flow will need your little efforts to realize complete secure data transmission.

This is an API that you have to expose to other parties across Credify network. This API redirects the request to a generated URL.

# Query params

# Basic properties

  • entity_id (string | undefined)
    • Unique ID in Credify generated for each OIDC client
  • phone_number (string | undefined)
    • Phone number of the user attempting to login
  • country_code (string | undefined)
    • Phone number's country code of the user attempting to login (e.g. 84, 81)

# Advanced properties

  • offer_code (string | undefined)
    • Offer code generated for each cross offer on serviceX Dashboard. This is not used for idX integration
  • package_code (string | undefined)
    • Product package code that users have selected in offer selection screen, if any

In this endpoint, an ephemeral encryption key pair may be generated and temporarily stored in your cache in order for you to decrypt the data passed through OpenID Connect. Also, you need to generate a signature to ensure this encryption key is belonging to you for other parties in this flow. Don't worry, our SDK will handle this crypto operations.

The basic properties are necessary for Credify, while the advanced properties depend on Service Providers' business needs. If they provide offers, offer_code and product_code should be handled in this endpoint.


This is the example of scopes you can access to.

scope description
openid OpenID Connect config (required)
profile Name, DOB, Gender
phone Phone number
email Email address
address Address
ekyc eKYC information
blockchain_id Addresses associated with blockchain accounts if any

Please refer to this section for its details.

# Implementation with SDK

What you have to do by yourself is

  • Configure OIDC response mode and type (authorization code flow? implicit flow?)
  • Generate a random state
  • Cache the privateKey (returned from the SDK) and state together
  • Node.js
  • Java
  • .NET
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const { Credify } = require("@credify/nodejs");

// You obtain these on the serviceX dashboard.
const signingPrivateKey = `-----BEGIN PRIVATE KEY-----
your private key...
-----END PRIVATE KEY-----`;
const apiKey = "YOUR_API_KEY";

const id = "YOUR_ORGANIZATION_ID";
const redirectUrl = "YOUR_REDIRECTION_URL";
const scopes = ["openid", "phone", "email", "profile"]; // depends on your config

const app = express();
app.use(bodyParser.json());
app.use(cors());

app.get("/oidc", async (req, res) => {
  // mode is `sandbox` or `production`
  const credify = await Credify.create(signingPrivateKey, apiKey, {
    mode: "sandbox",
  });

  // Generates a random value to identify this request afterwards.
  const state = Math.random().toString();

  // How to obtain access token through OIDC.
  const responseType = "code"; // "token"
  const responseMode = "form_post"; // "fragment"

  const options = { state, responseMode, responseType };
  if (req.query.phone_number) {
    options.phoneNumber = req.query.phone_number;
  } else if (req.query.entity_id) {
    options.userId = req.query.entity_id;
  }
  if (req.query.offer_code) {
    options.offerCode = req.query.offer_code;
  }
  if (req.query.package_code) {
    options.productCode = req.query.package_code;
  }

  const { oidcUrl, privateKey } = await credify.oidc.initiateOIDC(
    id,
    redirectUrl,
    scopes,
    options
  );

  // Store this `privateKey` along with `state`.

  res.redirect(oidcUrl);
});

In the OIDC setup URL, you need to redirect users to oidcUrl.

# User existence API endpoint - Backend

This tells Market that you have a specified user in your system. This helps you to receive only new users.

# Method

POST

# Authentication

This API is to be called by Credify with a JWT based access token. You need to validate the access token with token introspection API. This token introspection API requires you to have a token that is generated with your API key.

  1. Generate a temporary token with your API key. This needs organizataion or organization:introspect_token scope.
  2. Introspect the access token you get from the request. You will need to validate claim_provider:read_user_existence scope with this API.

# Request Body

  • phone_number: string
    • This is a phone number. e.g. "38123411234".
  • country_code: string
    • This is a country code. e.g. "+84".
  • id_number: string
    • This is an ID number of a document
  • id_ducument: string
    • Document type (e.g. passport, driving_license, national_id_card)

# Response Body

This will return exists boolean value.

{
  "data": {
    "exists": true
  }
}

# Implementation with SDK

What you have to do by yourself is

  • Check if this phone number exists in your system
  • Node.js
  • Java
  • .NET
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const { Credify } = require("@credify/nodejs");

// You obtain these on the serviceX dashboard.
const signingPrivateKey = `-----BEGIN PRIVATE KEY-----
your private key...
-----END PRIVATE KEY-----`;
const apiKey = "YOUR_API_KEY";

const app = express();
app.use(bodyParser.json());
app.use(cors());

app.post("/user-existence", async (req, res) => {
  // mode is `sandbox` or `production`
  const credify = await Credify.create(signingPrivateKey, apiKey, { mode: "sandbox" });

  // Provided you have `extractToken` function to obtain Bearer access token from Authorization header of the request.
  const token = extractToken(req);
  const isValidToken = await credify.auth.introspectToken(token, "claim_provider:read_user_existence");
  if (!isValidToken) {
    return res.status(401).send({ message: "Unauthorized" });
  }

  const phoneNumber = req.body.phone_number;
  const idNumber = req.body.id_number;
  const document = req.body.id_document;
  if (!phoneNumber && !idNumber && !document) {
    return res.status(400).send({ message: "Invalid query" });
  }
  if (!phoneNumber) {
    return res.status(403).send({ message: "This does not support checking with ID" });
  }

  // Check if this phone number exists in your system
  const exits = ...;

  res.json({ data: { exists } });
});

In case you want to have more flexible when introspecting the token (Eg: testing the API without forcing scope usage strictly or using the integration test), we have introspectTokenReturnResult function returns the introspect result like that:

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const { Credify } = require("@credify/nodejs");

// You obtain these on the serviceX dashboard.
const signingPrivateKey = `-----BEGIN PRIVATE KEY-----
your private key...
-----END PRIVATE KEY-----`;
const apiKey = "YOUR_API_KEY";

const app = express();
app.use(bodyParser.json());
app.use(cors());

app.post("/user-existence", async (req, res) => {
  // mode is `sandbox` or `production`
  const credify = await Credify.create(signingPrivateKey, apiKey, { mode: "sandbox" });

  // Provided you have `extractToken` function to obtain Bearer access token from Authorization header of the request.
  const token = extractToken(req);
  const introspectResult = await credify.auth.introspectTokenReturnResult(
    token
  );
  let validToken;
  if (
    introspectResult.data &&
    introspectResult.data.active &&
    introspectResult.data.scope.includes("claim_provider")
  ) {
    validToken = true;
  }

  if (!validToken) {
    return res.status(401).send({ message: "Unauthorized" });
  }

  const phoneNumber = req.body.phone_number;
  const idNumber = req.body.id_number;
  const document = req.body.id_document;
  if (!phoneNumber && !idNumber && !document) {
    return res.status(400).send({ message: "Invalid query" });
  }
  if (!phoneNumber) {
    return res.status(403).send({ message: "This does not support checking with ID" });
  }

  // Check if this phone number exists in your system
  const exits = ...;

  res.json({ data: { exists } });
});

# Redirection URLs - Backend

As the standard of OpenID Connect, you will need to handle redirection of users. In this redirection, you will obtain an authorization code or access token upon your configuration. If you receive an authorization code, you will need to exchange it with an access token. Basically, you set up a redirection URL of your frontend, and this backend logic will be used on that frontend page through API.

Token endpoint is described here.

Once you have received the access token, you can use it to retrieve user's encrypted profile data that the user approved to share with you. The API is described here.

You will need to use the encryption private key you have generated in the initial step of this OIDC flow.

If Service Providers provide offers, this endpoint should handle the offer redemption accordingly. By using offers, you as a Service Provider can filter out end-users that you want to reach out to. If you provide BNPL related offers, you can select users and have to onboard them to your service. In this case, the logic of this endpoint should handle onboarding if an offer code is being passed, while it should handle a normal OIDC process if it doesn't have an offer code.

# Implementation with SDK

What you have to do by yourself is

  • Develop the frontend to handle the OIDC redirection
  • Retrieve the ephemeral private key from your cache or DB
  • The SDK will handle fetching data and decrypting it and so you just need to continue your business requirement after obtaining the user profile
  • Node.js
  • Java
  • .NET
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const { Credify } = require("@credify/nodejs");

// You obtain these on the serviceX dashboard.
const signingPrivateKey = `-----BEGIN PRIVATE KEY-----
your private key...
-----END PRIVATE KEY-----`;
const apiKey = "YOUR_API_KEY";

const id = "YOUR_ORGANIZATION_ID";
const redirectUrl = "YOUR_REDIRECTION_URL";

const app = express();
app.use(bodyParser.json());
app.use(cors());

app.post("/oidc", async (req, res) => {
  // mode is `sandbox` or `production`
  const credify = await Credify.create(signingPrivateKey, apiKey, { mode: "sandbox" });

  // Provided you send `code` and `state` you have gotten to this endpoint
  const code = req.body.code;
  const state = req.body.state;
  const accessToken = await credify.oidc.generateAccessToken(id , code, redirectUrl);

  // If you are using implicit flow, you will receive a new access token on the frontend and so you will not have to call `generateAccessToken` like above.
  // const accessToken = req.body.access_token;

  // Retrieve the ephemeral encryption private key you have created in the initial step.
  const encryptionPrivateKey = ...;

  const data = await credify.oidc.userinfo(accessToken, encryptionPrivateKey);

  // Do whatever you want with the shared claims. e.g. onboarding to your service.

  // You may update the transaction status like following.
  const transactionAmount = {
    currency: "VND",
    value: 250000
  }
  await credify.offers.updateStatus(data.transaction_id, "COMPLETED", commission);

  res.json({ data });
});

And then, you just need to manage the session on your service.

# Redirection URLs - Frontend

Credify supports only web app for the redirection upon a successful OIDC session. Once an OIDC session is successfully completed, one of registered redirection URLs will be called with some parameters based on the configuration you have passed.

If you use authorization code flow, you will receive code, which you will need to use for generating a new access token. If implicit flow is stated, a new access token will be generated directly and passed in the request parameters. This handling is a common flow of OIDC, so this documentation will not explain this point.

OIDC redirection may have

  • offer_code
    • Offer code that a user has selected, if any
  • package_code
    • Package code that a user has selected, if any
  • kyc_reference
    • KYC reference ID if Service Providers have used their own eKYC endpoint
Last Updated: 1/24/2022, 11:53:45 AM