const fs = require("fs");
const jwt = require("jsonwebtoken");
const uuid = require("uuid");
const pem = fs.readFileSync("PATH_TO_PEM.pem");
const sdkId = "YOUR_SDK_ID";
const authURL = "https://auth.api.yoti.com/v1/oauth/token";
const issuedAt = Math.floor(Date.now() / 1000);
const expiry = issuedAt + 30 * 60;
function buildJWT() {
const claims = {
iss: "sdk:" + sdkId,
sub: "sdk:" + sdkId,
aud: authURL,
jti: uuid.v4(),
exp: expiry,
iat: issuedAt,
};
const headers = {
alg: "PS384",
typ: "JWT",
};
try {
const token = jwt.sign(claims, pem, {
algorithm: "PS384",
header: headers,
});
return token;
} catch (error) {
console.error("Error building JWT:", error);
}
}
const token = buildJWT();
console.log("Generated JWT successfully");
console.log(token);
using System;
using System.IO;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
using System.Text;
class Program
{
static void Main()
{
string pemPath = "PATH_TO_PEM.pem";
string sdkId = "YOUR_SDK_ID";
string authURL = "https://auth.api.yoti.com/v1/oauth/token";
string token = BuildJWT(pemPath, sdkId, authURL);
Console.WriteLine("Generated JWT: " + token);
}
static string BuildJWT(string pemPath, string sdkId, string authURL)
{
// Read PEM private key
string pem = File.ReadAllText(pemPath);
var rsa = RSA.Create();
rsa.ImportFromPem(pem.ToCharArray());
var securityKey = new RsaSecurityKey(rsa);
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSsaPssSha384);
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Iss, "sdk:" + sdkId),
new Claim(JwtRegisteredClaimNames.Sub, "sdk:" + sdkId),
new Claim(JwtRegisteredClaimNames.Aud, authURL),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Exp, (now + 30 * 60).ToString()),
new Claim(JwtRegisteredClaimNames.Iat, now.ToString())
};
var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = "sdk:" + sdkId,
Subject = new ClaimsIdentity(claims),
Audience = authURL,
Expires = DateTimeOffset.FromUnixTimeSeconds(now + 30 * 60).UtcDateTime,
SigningCredentials = credentials
};
var handler = new JwtSecurityTokenHandler();
var securityToken = handler.CreateJwtSecurityToken(tokenDescriptor);
return handler.WriteToken(securityToken);
}
}
package main
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"log"
"os"
"time"
"github.com/google/uuid"
)
func main() {
sdkId := "YOUR_SDK_ID"
pemPath := "PATH_TO_PEM.pem"
authURL := "https://auth.api.yoti.com/v1/oauth/token"
token, err := buildJWT(pemPath, sdkId, authURL)
if err != nil {
log.Fatal("Error building JWT:", err)
}
fmt.Println("Generated JWT successfully")
fmt.Println(token)
}
func buildJWT(pemPath, sdkId, authURL string) (string, error) {
pemData, err := os.ReadFile(pemPath)
if err != nil {
return "", fmt.Errorf("failed to read PEM file: %w", err)
}
block, _ := pem.Decode(pemData)
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
// Try PKCS8 if PKCS1 fails
parsed, err2 := x509.ParsePKCS8PrivateKey(block.Bytes)
if err2 != nil {
return "", fmt.Errorf("failed to parse private key: %w", err)
}
key = parsed.(*rsa.PrivateKey)
}
now := time.Now().Unix()
header, _ := json.Marshal(map[string]string{
"alg": "PS384",
"typ": "JWT",
})
claims, _ := json.Marshal(map[string]interface{}{
"iss": "sdk:" + sdkId,
"sub": "sdk:" + sdkId,
"aud": authURL,
"jti": uuid.New().String(),
"iat": now,
"exp": now + 300,
})
signingInput := b64url(header) + "." + b64url(claims)
hash := crypto.SHA384.New()
hash.Write([]byte(signingInput))
signature, err := rsa.SignPSS(rand.Reader, key, crypto.SHA384, hash.Sum(nil), &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash,
})
if err != nil {
return "", fmt.Errorf("failed to sign JWT: %w", err)
}
return signingInput + "." + b64url(signature), nil
}
func b64url(data []byte) string {
return base64.RawURLEncoding.EncodeToString(data)
}
<?php
require_once __DIR__ . '/vendor/autoload.php';
$pemPath = 'PATH_TO_PEM.pem';
$sdkId = 'YOUR_SDK_ID';
$authURL = 'https://auth.api.yoti.com/v1/oauth/token';
$token = buildJWT($pemPath, $sdkId, $authURL);
echo "Generated JWT: " . $token . "\n";
function buildJWT(string $pemPath, string $sdkId, string $authURL): string
{
$pem = file_get_contents($pemPath);
$now = time();
$header = json_encode(['alg' => 'PS384', 'typ' => 'JWT']);
$claims = json_encode([
'iss' => 'sdk:' . $sdkId,
'sub' => 'sdk:' . $sdkId,
'aud' => $authURL,
'jti' => bin2hex(random_bytes(16)),
'iat' => $now,
'exp' => $now + 300,
]);
$signingInput = base64UrlEncode($header) . '.' . base64UrlEncode($claims);
$rsaKey = \phpseclib3\Crypt\PublicKeyLoader::load($pem);
$rsaKey = $rsaKey
->withPadding(\phpseclib3\Crypt\RSA::SIGNATURE_PSS)
->withHash('sha384')
->withMGFHash('sha384');
$signature = $rsaKey->sign($signingInput);
return $signingInput . '.' . base64UrlEncode($signature);
}
function base64UrlEncode(string $data): string
{
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
import json
import time
import os
import base64
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
sdk_id = "YOUR_SDK_ID"
pem_path = "PATH_TO_PEM.pem"
auth_url = "https://auth.api.yoti.com/v1/oauth/token"
def b64url(data: bytes) -> str:
return base64.urlsafe_b64encode(data).rstrip(b"=").decode()
def build_jwt(pem_path: str, sdk_id: str, auth_url: str) -> str:
with open(pem_path, "rb") as f:
private_key = serialization.load_pem_private_key(f.read(), password=None)
now = int(time.time())
header = json.dumps({"alg": "PS384", "typ": "JWT"}, separators=(",", ":"))
claims = json.dumps({
"iss": f"sdk:{sdk_id}",
"sub": f"sdk:{sdk_id}",
"aud": auth_url,
"jti": os.urandom(16).hex(),
"iat": now,
"exp": now + 300,
}, separators=(",", ":"))
signing_input = f"{b64url(header.encode())}.{b64url(claims.encode())}"
signature = private_key.sign(
signing_input.encode(),
padding.PSS(
mgf=padding.MGF1(hashes.SHA384()),
salt_length=padding.PSS.MAX_LENGTH,
),
hashes.SHA384(),
)
return f"{signing_input}.{b64url(signature)}"
token = build_jwt(pem_path, sdk_id, auth_url)
print("Generated JWT:", token)
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import java.io.FileReader;
import java.security.PrivateKey;
import java.time.Instant;
import java.util.Date;
import java.util.UUID;
public class JwtBuilder {
private static final String SDK_ID = "YOUR_SDK_ID";
private static final String PEM_PATH = "PATH_TO_PEM.pem";
private static final String AUTH_URL = "https://auth.api.yoti.com/v1/oauth/token";
public static void main(String[] args) throws Exception {
PrivateKey privateKey = loadPrivateKey(PEM_PATH);
Instant now = Instant.now();
Instant expiry = now.plusSeconds(30 * 60);
String token = Jwts.builder()
.setIssuer("sdk:" + SDK_ID)
.setSubject("sdk:" + SDK_ID)
.setAudience(AUTH_URL)
.setId(UUID.randomUUID().toString())
.setIssuedAt(Date.from(now))
.setExpiration(Date.from(expiry))
.signWith(privateKey, SignatureAlgorithm.PS384)
.compact();
System.out.println("Generated JWT successfully");
System.out.println(token);
}
private static PrivateKey loadPrivateKey(String pemPath) throws Exception {
try (PEMParser parser = new PEMParser(new FileReader(pemPath))) {
Object parsed = parser.readObject();
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
if (parsed instanceof org.bouncycastle.openssl.PEMKeyPair keyPair) {
return converter.getPrivateKey(keyPair.getPrivateKeyInfo());
} else if (parsed instanceof PrivateKeyInfo privateKeyInfo) {
return converter.getPrivateKey(privateKeyInfo);
}
throw new IllegalArgumentException("Unsupported PEM format");
}
}
}