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);
# pip3 install cryptography pyjwt
import base64
from cryptography.hazmat.primitives.serialization import Encoding
from cryptography.hazmat.primitives.serialization.pkcs12 import load_key_and_certificates
import hashlib
import jwt
import time
pfx_path = './sample.pfx'
with open(pfx_path, 'rb') as f:
pfx_contents = f.read()
pfx_password = 'a-password'
private_key, main_cert, _ = load_key_and_certificates(pfx_contents, pfx_password.encode())
# get certificate fingerprints (x5t, kid)
cert_der = main_cert.public_bytes(encoding=Encoding.DER)
cert_sha1 = hashlib.sha1(cert_der)
x5t = base64.b64encode(cert_sha1.digest()).decode().rstrip('=')
kid = cert_sha1.hexdigest().upper()
# create jwt payload
user_guid = 'your-user-guid-here'
now = int(time.time())
payload = {
"sub": user_guid,
"iat": now - 30,
"exp": now + (60 * 60), # 1 hour
"iss": "Self",
"aud": "vaultn.com",
}
jwt_token = jwt.encode(
payload,
private_key,
headers={
'alg':'RS256',
'typ': 'JWT',
'kid': kid,
'x5t': x5t,
},
)
- 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.
Updated 3 months ago