Migration of Public APIs using Basic Auth in 3.x to Public APIs using Token based Auth in 4.x
search cancel

Migration of Public APIs using Basic Auth in 3.x to Public APIs using Token based Auth in 4.x

book

Article ID: 330379

calendar_today

Updated On:

Products

VMware Cloud Foundation

Issue/Introduction

With the release of VMware Cloud Foundation 4.0, all the SDDC Manager APIs use a token-based authentication model for API invocation. The previous VMware Cloud Foundation 3.x releases use basic auth model, which is deprecated in the VCF 4.x releases. This document captures the steps needed to migrate to using token-based authentication while invoking public APIs

Symptoms:
If the customer tries to execute an API by using Basic Authentication in 4.x, the following error will be thrown “Authorization Header is missing or not in correct format”

Example:

 curl -k -u ‘username:password’ https://10.0.0.4/v1/users
{"status":401,"message":"Authorization Header is missing or not in correct format"}



Cause

With VCF 4.x release all the Public APIs are using Token based Authentication instead of basic authentication

Resolution

Not Applicable (Starting from 4.x Release all the public APIs are based on token-based authentication)

Workaround:
API usage in 4.x

 All SDDC Manager APIs are secured using token-based authentication.
 • As a first step before invocation of any API, an access token has to be obtained using the TOKEN API.
 • Invoking the Token API returns a token pair - access token and refresh token.
 • To invoke an API, the access token has to be passed in the Authorization header as a Bearer token.
 • Access token has limited validity. Validity of the access token is currently 1 hour and of the refresh token is 24 hours.
 • Once the access token is expired a Refresh token can be used to renew the access token.

Steps for generating the token and consuming is documented below.

1. GENERATE THE TOKEN USING TOKEN API

Prerequisites :
VCF Credentials

 • User created in PSC and associated as an ADMIN , OPERATOR or VIEWER role in VMware Cloud Foundation
 • Username
 • Password
 
CURL Request

curl -X POST -H "Content-Type: application/json" -d '{"username": "[email protected]","password": "temp!"}' https://sddcmanagerIp/v1/tokens


Example

Invoke the API with the right credentials. The credentials passed in the payload are of users created in PSC and mapped to either ADMIN, OPERATOR or VIEWER role in VCF.

[root@test-linuxJump ~]# curl -X POST -H "Content-Type: application/json" -d '{"username": "[email protected]","password": "****"}' https://10.0.0.4/v1/tokens | json_pp
  % Total % Received % Xferd Average Speed Time Time Time Current
                                 Dload Upload Total Spent Left Speed
100 730 0 662 100 68 710 72 --:--:-- --:--:-- --:--:-- 710
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZmI2MjNkZS1kZjIwLTQ1NWEtOWQ3NC1mYzgwZmFjNzM5ZGUiLCJpYXQiOjE1ODIxOTcxODcsInN1YiI6InZjZi1zZWN1cmUtdXNlckB2c3BoZXJlLmxvY2FsIiwiaXNzIjoidmNmLWF1dGgiLCJhdWQiOiJzZGRjLXNlcnZpY2VzIiwibmJmIjoxNTgyMTk3MTg3LCJleHAiOjE1ODIyMDA3ODcsInVzZXIiOiJ2Y2Ytc2VjdXJlLXVzZXJAdnNwaGVyZS5sb2NhbCIsIm5hbWUiOiJ2Y2Ytc2VjdXJlLXVzZXJAdnNwaGVyZS5sb2NhbCIsInNjb3BlIjpbIkJBQ0tVUF9DT05GSUdfUkVBRCIsIkNSRURFTlRJQUxfUkVBRCIsIlVTRVJfV1JJVEUiLCJPVEhFUl9XUklURSIsIkJBQ0tVUF9DT05GSUdfV1JJVEUiLCJPVEhFUl9SRUFEIiwiVVNFUl9SRUFEIiwiQ1JFREVOVElBTF9XUklURSJdfQ._92IFJCQsbRbAWd4PQmBDczWXtuVCWPOsL1ZyCdKEMU",
  "refreshToken": {
    "id": "3c6b3c30-####-####-####-########928"
  }
}


2. INVOKE THE API USING THE ACCESS TOKEN

Use the accessToken generated in previous step, and pass this token as Bearer token in Authorization header. Here is the sample API invocation that uses a Bearer Token in Authorization header to list users using VCF Public API

Curl Request

curl -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" https://sddcmanagerIp/v1/example


Example

[root@test-linuxJump ~]# curl -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhZmI2MjNkZS1kZjIwLTQ1NWEtOWQ3NC1mYzgwZmFjNzM5ZGUiLCJpYXQiOjE1ODIxOTcxODcsInN1YiI6InZjZi1zZWN1cmUtdXNlckB2c3BoZXJlLmxvY2FsIiwiaXNzIjoidmNmLWF1dGgiLCJhdWQiOiJzZGRjLXNlcnZpY2VzIiwibmJmIjoxNTgyMTk3MTg3LCJleHAiOjE1ODIyMDA3ODcsInVzZXIiOiJ2Y2Ytc2VjdXJlLXVzZXJAdnNwaGVyZS5sb2NhbCIsIm5hbWUiOiJ2Y2Ytc2VjdXJlLXVzZXJAdnNwaGVyZS5sb2NhbCIsInNjb3BlIjpbIkJBQ0tVUF9DT05GSUdfUkVBRCIsIkNSRURFTlRJQUxfUkVBRCIsIlVTRVJfV1JJVEUiLCJPVEhFUl9XUklURSIsIkJBQ0tVUF9DT05GSUdfV1JJVEUiLCJPVEhFUl9SRUFEIiwiVVNFUl9SRUFEIiwiQ1JFREVOVElBTF9XUklURSJdfQ._92IFJCQsbRbAWd4PQmBDczWXtuVCWPOsL1ZyCdKEMU" https://10.0.0.4/v1/users | json_pp
  % Total % Received % Xferd Average Speed Time Time Time Current
                                 Dload Upload Total Spent Left Speed
100 2149 0 2149 0 0 3446 0 --:--:-- --:--:-- --:--:-- 3449
{
   "elements" : [
      {
         "domain" : "VSPHERE.LOCAL",
         "creationTimestamp" : "2020-02-19T13:50:59.783Z",
         "name" : "[email protected]",
         "type" : "USER",
         "id" : "e906b68a-####-####-####-########a1b",
         "role" : {
            "id" : "d40632bd-####-####-####-########3c5"
         }
      }
   ]
}


3. GENERATE A NEW ACCESS TOKEN USING REFRESH TOKEN IF THE ACCESS TOKEN IS EXPIRED

Refresh tokens are a special type of credential tokens that is used to generate access tokens. This workflow is used when access tokens have expired. They generate a new access token when the current access token either expires or is invalid or to generate additional tokens. Typical expiration time of access token is 1 hour and that of refresh tokens is 1 day

Prerequisites:
The following data is required

  • Refresh token obtained when token pair is generated using the TOKEN API


Curl Request

curl -X PATCH -H "Content-Type: application/json" -d 'refresh-token' https://sddcmanagerIp/v1/tokens/access-token/refresh


Examples
Example of token getting expired

root@sddc-manager [ ~ ]# curl -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' https://10.0.0.4/v1/sddc-manager -k | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 173 100 173 0 0 2436 0 --:--:-- --:--:-- --:--:-- 2471
{
"status": 401,
"message": "JWT expired at 2021-03-11T02:27:33Z. Current time: 2021-03-11T02:29:21Z, a difference of 108620 milliseconds. Allowed clock skew: 0 milliseconds."
}


Generate new access token using Refresh token

root@sddc-manager [ /home/vcf ]# curl 'https://10.0.0.4/v1/tokens/access-token/refresh' -X PATCH -H 'Content-Type: application/json' -H 'Accept: application/json' -d '"cfd6e2df-####-####-####-########d8a"' -k
{
"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJhNjg5Njk0YS02Njc1LTQwYzQtYTk1NS03YWE3OWI3NDM3MzciLCJpYXQiOjE2MjQ1Mzc1ODMsInN1YiI6ImFkbWluaXN0cmF0b3JAdnNwaGVyZS5sb2NhbCIsImlzcyI6InZjZi1hdXRoIiwiYXVkIjoic2RkYy1zZXJ2aWNlcyIsIm5iZiI6MTYyNDUzNzU4MywiZXhwIjoxNjI0NTQxMTgzLCJ1c2VyIjoiYWRtaW5pc3RyYXRvckB2c3BoZXJlLmxvY2FsIiwibmFtZSI6ImFkbWluaXN0cmF0b3JAdnNwaGVyZS5sb2NhbCIsInNjb3BlIjpbIlNERENfRkVERVJBVElPTl9XUklURSIsIkFWTl9XUklURSIsIlNERENfTUFOQUdFUl9SRUFEIiwiQ0VSVF9XUklURSIsIkNPTVBPU0FCSUxJVFlfV1JJVEUiLCJMSUNFTlNFX0tFWV9SRUFEIiwiQ09NUE9TQUJJTElUWV9SRUFEIiwiRURHRV9DTFVTVEVSX1dSSVRFIiwiVVNFUl9SRUFEIiwiQ1JFREVOVElBTF9XUklURSIsIkJBQ0tVUF9DT05GSUdfUkVBRCIsIkNMVVNURVJfV1JJVEUiLCJBVk5fUkVBRCIsIlZBU0FfUFJPVklERVJfUkVBRCIsIkRPTUFJTl9XUklURSIsIkNFSVBfUkVBRCIsIlNPU19XUklURSIsIlNERENfTUFOQUdFUl9XUklURSIsIk5UUF9XUklURSIsIkRFUE9UX0NPTkZJR19XUklURSIsIkRFUE9UX0NPTkZJR19SRUFEIiwiSE9TVF9XUklURSIsIkJBQ0tVUF9SRVNUT1JFX1JFQUQiLCJDRVJUX1JFQUQiLCJVU0VSX1dSSVRFIiwiVVBHUkFERV9SRUFEIiwiT1RIRVJfUkVBRCIsIlNPU19SRUFEIiwiU0VDVVJJVFlfQ09ORklHX1JFQUQiLCJDUkVERU5USUFMX1JFQUQiLCJIT1NUX1JFQUQiLCJDRUlQX1dSSVRFIiwiT1RIRVJfV1JJVEUiLCJMSUNFTlNFX0tFWV9XUklURSIsIkNBX1JFQUQiLCJORVRXT1JLX1BPT0xfV1JJVEUiLCJXQ1BfUkVBRCIsIkJBQ0tVUF9SRVNUT1JFX1dSSVRFIiwiTlRQX1JFQUQiLCJFREdFX0NMVVNURVJfUkVBRCIsIkJBQ0tVUF9DT05GSUdfV1JJVEUiLCJXQ1BfV1JJVEUiLCJTRVJWSUNFX0FDQ09VTlRfV1JJVEUiLCJORVRXT1JLX1BPT0xfUkVBRCIsIkNBX1dSSVRFIiwiQ0xVU1RFUl9SRUFEIiwiVkFTQV9QUk9WSURFUl9XUklURSIsIkROU19XUklURSIsIlZSU0xDTV9XUklURSIsIkROU19SRUFEIiwiU0VSVklDRV9BQ0NPVU5UX1JFQUQiLCJTRERDX0ZFREVSQVRJT05fUkVBRCIsIkRPTUFJTl9SRUFEIiwiVlJTTENNX1JFQUQiLCJVUEdSQURFX1dSSVRFIl0sInJvbGUiOlsiQURNSU4iXX0.K8zA-YhiLV32etkJgkakwyoGS30Vi-rRMgS2XfvuL2g"}



JAVA Code examples

Generate Access and Refresh Token

HttpPost post = new HttpPost("https://sddc-manager.vrack.vsphere.local/v1/tokens");
StringBuilder json = new StringBuilder();
/* Form the input data to be passed to the API */
json.append("{");
json.append("\"username\":\"[email protected]\",");
json.append("\"password\":\"****\"");
json.append("}");
post.setHeader("Content-Type", "application/json");
// send a JSON data
post.setEntity(new StringEntity(json.toString()));
try (CloseableHttpClient httpClient = HttpClients.createDefault();
     CloseableHttpResponse response = httpClient.execute(post)) {
     result = EntityUtils.toString(response.getEntity());
}
JSONObject object = new JSONObject(result);
/* Extract the access token from result of calling /v1/tokens */
String accessToken = object.get("accessToken").toString();
/* Extract the refresh token from result of calling /v1/tokens */
JSONObject refreshTokenObject = (JSONObject) object.get("refreshToken");
String refreshToken = refreshTokenObject.get("id").toString();

    
Code for calling a sample API with access token passed in HEADER

HttpGet request = new HttpGet("https://sddc-manager.vrack.vsphere.local/v1/users");
request.setHeader("Content-Type", "application/json");
/*Pass the accessToken as bearer token in the header */
request.setHeader("Authorization", "Bearer " + accessToken);
try (CloseableHttpClient httpClient = HttpClients.createDefault();
    CloseableHttpResponse response = httpClient.execute(request)) {
    String result = EntityUtils.toString(response.getEntity());
     System.out.println("OUTPUT of the API is " + result);
    }


Use a refresh token to generate new access token when the token is expired

HttpPatch httpPatch =
        new HttpPatch(
            "https://sddc-manager.vrack.vsphere.local/v1/tokens/access-token/refresh");
httpPatch.setEntity(new StringEntity(refreshToken));
httpPatch.setHeader("Content-Type", "application/json");
 try (CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = httpClient.execute(httpPatch)) {
      result = EntityUtils.toString(response.getEntity());
/*If the generated token is enclosed with inverted commas remove that to avoid token mismatch error */
      if (result.startsWith("\"") && result.endsWith("\"")) {
        result = result.substring(1, result.length() - 1);
      }
}
String newAccessToken = result;