How to get an access token?

Once the certificate is created and uploaded, it is now used for authenticating against the API.

The following code snippets in (currently available for C#, PHP, Java & Node.js) demonstrates how to acquire the token string.

public string GenerateToken(string vaultGuid) 
{ 
  var tokenHandler = new JwtSecurityTokenHandler(); 
  var cert = new X509Certificate2("{pfxFilePath}", "{pfxPassword}"); 
	var cred = new X509SigningCredentials(cert); 
 
	var tokenDescriptor = new SecurityTokenDescriptor { 
    Issuer = "Self", 
    Audience = "VAULTN", 
    Subject = new ClaimsIdentity(new Claim[] { 
      new Claim(JwtRegisteredClaimNames.Sub, userGuid)  }), 
    Expires = DateTime.UtcNow.AddDays(365), 
    SigningCredentials = cred 
 	};
  
 	var token = tokenHandler.CreateToken(tokenDescriptor); 
	var retval = tokenHandler.WriteToken(token);
  
  return retval;
}
<?php

require __DIR__ . "/vendor/autoload.php";
use Firebase\JWT\JWT;

// Load private key, certificate, and CA certificates from PFX file
$pfxFile = "sample.pfx";
$password = "password";
$certs = [];

if (openssl_pkcs12_read(file_get_contents($pfxFile), $certs, $password)) {
    // PFX file loaded successfully
    $privateKey = $certs["pkey"];
    $certificate = $certs["cert"];
} else {
    // Failed to load PFX file
    echo "Failed to load PFX file.";
}

// Create hash value from certificate
$certificateHash = openssl_x509_fingerprint($certificate, "sha1", true);

// Convert hash value into base64url
$base64urlHash = base64_encode($certificateHash);
$x5t = str_replace(["+", "/", "="], ["", "", ""], $base64urlHash);
$kid = strtoupper(openssl_x509_fingerprint($certificate, "sha1", false));

// Use the $base64urlHash as needed
$header = [
    "typ" => "JWT",
    "alg" => "RS256", // Ensure this matches your signing algorithm
    "x5t" => $x5t,
];

// Define your payload
$payload = [
    "iss" => "Self",
    "aud" => "identity.vaultn.com",
    "sub" => "", // your VaultGuid here
    "iat" => time(),
    "exp" => time() + (60 * 60 * 24 * 365), // Token expiration time (1 year)
];

// Generate the JWT token
$jwt = JWT::encode($payload, $privateKey, "RS256", $kid, $header);

echo $jwt;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;

import org.apache.commons.codec.binary.Base64;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JOSEObjectType;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

private String getAuthToken() throws IOException {
   try {
      char[] password = crtPass.toCharArray();

      KeyStore keyStore = KeyStore.getInstance("PKCS12");
      try (FileInputStream fileInputStream = new FileInputStream(crtPath)) {
         keyStore.load(fileInputStream, password);
      }

      PrivateKey privateKey = null;
      Certificate certificate = null;

      Enumeration<String> aliases = keyStore.aliases();
      while (aliases.hasMoreElements()) {
         String alias = aliases.nextElement();
         if (keyStore.isKeyEntry(alias)) {
            privateKey = (PrivateKey) keyStore.getKey(alias, password);
            certificate = keyStore.getCertificate(alias);
            break;
         }
      }

      MessageDigest sha1Digest = MessageDigest.getInstance("SHA-1");

      if (certificate == null) {
         throw new IOException("Error while reading the certificate. Certificate cannot be null.");
      }

      byte[] certificateHash = sha1Digest.digest(certificate.getEncoded());

      String base64urlHash = Base64.encodeBase64URLSafeString(certificateHash);
      String x5t = base64urlHash.replace("=", "");

      String kid = getHexEncodedFingerprint((X509Certificate) certificate);

      JWSHeader jwsHeader = new JWSHeader.Builder(JWSAlgorithm.RS256)
            .type(JOSEObjectType.JWT)
            .x509CertThumbprint(new Base64URL(x5t))
            .keyID(kid)
            .build();

      JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
            .issuer(crtIssuer)
            .audience(crtAudience)
            .subject(userUid)
            .issueTime(new Date())
            .expirationTime(new Date(System.currentTimeMillis() + (60L * 60 * 24 * 365 * 1000))) // Token expiration time (1 year)
            .build();

      JWSSigner signer = new RSASSASigner(privateKey);
      SignedJWT signedJWT = new SignedJWT(jwsHeader, claimsSet);
      signedJWT.sign(signer);

      String jwt = signedJWT.serialize();
      return jwt;
   } catch (JOSEException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException | KeyStoreException e) {
      throw new IOException(e.getMessage());
   }
}

private static String getHexEncodedFingerprint(X509Certificate cert) throws IOException {
   try {
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      byte[] digest = md.digest(cert.getEncoded());
      return bytesToHex(digest);
   } catch (Exception e) {
      throw new IOException(e.getMessage());
   }
}

private static String bytesToHex(byte[] bytes) {
   StringBuilder sb = new StringBuilder();
   for (byte b : bytes) {
      sb.append(String.format("%02X", b));
   }
   return sb.toString();
}
const forge = require('node-forge');
const fs = require('fs');
const jwt = require('jsonwebtoken');
 
// Load PFX file
const pfxPath = './sample.pfx';
const pfxPassword = 'password';
const pfxData = fs.readFileSync(pfxPath, 'binary');
 
// Parse PFX file
const pfxAsn1 = forge.asn1.fromDer(pfxData, false);
const pfx = forge.pkcs12.pkcs12FromAsn1(pfxAsn1, false, pfxPassword);
 
// Extract private key and certificate
let privateKey, certificate;
for (const safeContent of pfx.safeContents) {
  for (const safeBag of safeContent.safeBags) {
    if (safeBag.type === forge.pki.oids.certBag) {
      // Extract certificate
      certificate = forge.pki.certificateToPem(safeBag.cert);
    } else if (safeBag.type === forge.pki.oids.keyBag || safeBag.type === forge.pki.oids.pkcs8ShroudedKeyBag) {
      // Extract private key
      privateKey = forge.pki.privateKeyToPem(safeBag.key);
    }
  }
}
 
const certDer = forge.asn1.toDer(forge.pki.certificateToAsn1(forge.pki.certificateFromPem(certificate))).getBytes();
const x5t = forge.util.encode64(forge.md.sha1.create().update(certDer).digest().bytes());
const kid = forge.md.sha1.create().update(certDer).digest().toHex();
 
const payload = {
    sub: userGuid,
    iat: Math.floor(Date.now() / 1000) - 30,
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
    iss: "",
    aud: ""
 
  };
  
  const signOptions = {
    algorithm: "RS256",    
    header: {
      x5t: x5t.replace(/=/g, ''),
      kid: kid.toUpperCase()
    }
  };
  
  // Sign JWT
  const token = jwt.sign(payload, privateKey, signOptions);
  
  console.log("JWT Token:", token);
  • Replace the .pfx file path and password accordingly.
  • While defining the Claim, use your VaultN Guid as the parameter vaultGuid _found under _VaultN -> Settings.
  • It is to be used as a Bearer token.

Additional Notes

  • For C#
    • Add System.IdentityModel.Tokens.Jwt as a reference to your project.
    • AddDays() -> defines the validity period for the claim. It can be as long as the certificate is good for.
  • For PHP
    • Use command "composer require firebase/php-jwt".
    • The used PHP version is 5.6.
    • "exp" => time() + (60 * 60 * 24 * 365) -> last parameter defines the validity of the token in seconds.