remkohdev
  • Learn to Code
  • About Me
  • CI/CD
    • DevOps101
      • Welcome
  • OpenShift
    • Setup OpenShift
      • Setup Minishift
    • Builds
      • Source-to-Image (S2I)
        • Setup S2I
        • Build, Run, Deploy from Source
      • Jenkins Pipeline
    • Jenkins as a Service
      • Setup Jenkins on Openshift
      • Create a Pipeline for Java Spring Boot
  • Istio
    • Setup Istio on IKS
      • Login to IKS
    • Setup Istio on Openshift 3.11
    • Traffic Shifts with a VirtualService
    • Telemetry of Metrics using Prometheus
    • Telemetry of Distributed Tracing using Jaeger
    • Security with Mutual TLS (mTLS)
  • Apache Kafka
    • Setup Apache Kafka on IBM Cloud
    • Setup Apache Kafka on OpenShift
    • Produce and Consume Streams with Kafka Console Tools
    • Produce and Consume Streams with Spring Boot
    • Using the Event Streams CLI
    • Kafka Admin API
  • API Connect
    • APIC CLI
      • Manage API Lifecycle with apic
    • Securing your API
      • Setup AppID
      • Setup API Connect
      • Optional: Add Node-RED Test Server
      • Add 3rd Party OAuth OIDC
        • Create a Custom AppID API
        • Add a Security Definition to your API
Powered by GitBook
On this page

Was this helpful?

  1. API Connect
  2. Securing your API
  3. Add 3rd Party OAuth OIDC

Create a Custom AppID API

PreviousAdd 3rd Party OAuth OIDCNextAdd a Security Definition to your API

Last updated 5 years ago

Was this helpful?

The Custom AppID API handles the workflow to call the AppID POST /token and the POST /introspect endpoints that constitute the OAuth OpenID Connect OAuth 2.0 authorization workflow. The GatewayScripts are responsible for parsing the incoming requests from the previous nodes and outgoing responses for the next nodes.

The Custom AppID API implements the same workflow as the optional Node-RED Test Server, but then embedded in the DataPower Gateway that is part of the API Connect instance.

  1. In API Connect Create a new API

    • Go to the API Connect Dashboard,

    • From the Home menu, go to Drafts,

  • Go to the APIs tab,

  • Create a new API and click the Add + button,

  • Select New API

  • Edit the API details:

    • Title: Custom AppID API,

    • Name, Base Path, and Version will auto-populate,

    • In Additional properties,

    • For Create API using template select Default,

    • For Target endpoint set /introspect,

    • Under Security, for Identify using select None,

    • Check Enable CORS,

    • Under Gateway select DataPower Gateway,

    • Click Create API,

  • Add New Path

    • Go to the Paths section,

    • Add a new Path and click the + icon,

    • Rename /path-1 to /introspect,

    • Click the Save icon,

  • Add the /token and /introspect Workflow to the Policy Assembly,

    • Go to the Policy Assembly section and click Edit assembly,

    • In the Assemble editor, a new assembly will load with a default invoke action,

  • In the Assemble editor, consecutively, create 3 GatewayScripts:

  • From the Policies section, drag a GatewayScript node onto the workflow, to parse the credentials of the incoming request,

    • Rename the Title to gs - credentials,

    • Paste the following Gateway script into the editor window,

var sm = require('service-metadata');

// decode username:password in Authorization header 
var authHeader = apim.getvariable('request.headers.authorization');
var encodedAuth = authHeader.replace("Basic ");
var decodedAuth = new Buffer(encodedAuth, 'base64').toString('ascii');
var credentials = decodedAuth.split(":");
var username = credentials[0];
var password = credentials[1];
var granttype = "password";

// handle optional x-introspect
var xUsername = apim.getvariable('request.headers.x-introspect-username');
var xPassword = apim.getvariable('request.headers.x-introspect-password');
var xGranttype = apim.getvariable('request.headers.x-introspect-granttype'); 
if(xUsername){
    username=xUsername;
}
if(xPassword){
    password=xPassword;
}
if(xGranttype){
    granttype=xGranttype;
}

// pass credentials
apim.setvariable('request.body.appid_username', username);
apim.setvariable('request.body.appid_password', password);
apim.setvariable('request.body.appid_granttype', granttype);
  • Save the Assemble to prevent loss,

  • From the Policies section, drag another GatewayScript node onto the workflow, to parse the user credentials from the previous step, and send a POST /token request to the Open ID Connect Identity Provider and receive the access_token, id_token, token_type, and expires_in the properties of the response,

    • Rename the Title to gs - token,

    • Paste the following Gateway script into the editor window,

var urlopen = require('urlopen');

var username = apim.getvariable('request.body.appid_username');
var password = apim.getvariable('request.body.appid_password');
var granttype = apim.getvariable('request.body.appid_granttype');

var requestData = `grant_type=${granttype}&username=${username}&password=${password}`;

var options = {
    target: 'https://<TODO APPID REGION>.appid.cloud.ibm.com/oauth/v4/<TODO: APPID INSTANCE ID>/token',
    method: 'POST',
    headers: {
        Authorization: 'Basic <TODO: BASIC AUTH WITH APPID CLIENTID AND SECRET>'
    },
    contentType: 'application/x-www-form-urlencoded',
    timeout: 60,
    sslClientProfile: 'webapi-sslcli-mgmt',
    data: requestData
};

urlopen.open(options, function(error, response) {
  if (error) {
    session.output.write("urlopen error: "+JSON.stringify(error));
  } else {
    var responseStatusCode = response.statusCode;
    var responseReasonPhrase = response.reasonPhrase;
    apim.setvariable('appid-token-response-statuscode', responseStatusCode); 
    apim.setvariable('appid-token-response-reason', responseReasonPhrase); 
    response.readAsJSON(function(error, json) { 
      if (error){
        throw error ;
      } else {
        apim.setvariable('request.body.appid_token_response_body', json); 
      }
    });
  }
});
  • Now we have the identity token, from the Policies section, drag a last GatewayScript node onto the workflow, to call the AppID POST /introspect API to validate the user's identity token,

    • Rename the Title to gs - introspect,

    • Paste the following Gateway script into the editor window,

var urlopen = require('urlopen');

var tokenResponseJson = apim.getvariable('request.body.appid_token_response_body');
var idToken = tokenResponseJson.id_token;
var requestData = `token=${idToken}`;

var options = {
    target: 'https://<TODO APPID REGION>.appid.cloud.ibm.com/oauth/v4/<TODO: APPID INSTANCE ID>/introspect',
    method: 'POST',
    headers: {
        Authorization: 'Basic <TODO: BASIC AUTH WITH APPID CLIENTID AND SECRET>'
    },
    contentType: 'application/x-www-form-urlencoded',
    timeout: 60,
    sslClientProfile: 'webapi-sslcli-mgmt',
    data: requestData
};

urlopen.open(options, function(error, response) {
  if (error) {
    session.output.write("urlopen error: "+JSON.stringify(error));
  } else {
    var responseStatusCode = response.statusCode;
    var responseReasonPhrase = response.reasonPhrase;
    apim.setvariable('appid-token-response-statuscode', responseStatusCode); 
    apim.setvariable('appid-token-response-reason', responseReasonPhrase); 
    response.readAsJSON(function(error, json) { 
      if (error){
        throw error ;
      } else {
        session.output.write(json);
        apim.output('application/json');
      }
    });
  }
});
  • The response of the last GatewayScript gs - introspectis a simple true|false value, which API Connect handles to return or proceed with the original API request,

  • From the top right menu, click the manage dropdown and select Generate a default product if you do not have an existing product,

  • Click Create product to create the New Product,

  • This will stage your new API to the Sandbox,

  • Click Explore and select Sandbox,

  • Click the POST /introspect operation in the left menu, and review the API reference values,

  • Copy the full URL, you need it to configure the Security Definition of your API, e.g. POST `https://api.<api region>.apiconnect.appdomain.cloud/<username>-dev/sb/custom-appid-api/introspect`,