Authentication#

Self-signed JWT#

Before getting started, ensure a developer account has been created for you. You will receive an email containing your private key and key ID.

Please speak with your GroupVAN integrator to receive your client ID and user IDs.

Open a terminal and navigate to your project directory, then run:

pip3 install PyJWT

Open a terminal and navigate to your project directory, then run:

npm install jsonwebtoken
<!-- Maven (pom.xml) -->
<dependencies>
  <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
  </dependency>
  <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
  </dependency>
</dependencies>
// Gradle (build.gradle)
dependencies {
    implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
}
import jwt
from uuid import uuid4
from datetime import datetime, timedelta, timezone

private_key = YOUR_PRIVATE_KEY
key_id = YOUR_KEY_ID
client_id = YOUR_CLIENT_ID
user_id = YOUR_USER_ID

integration = YOUR_INTEGRATION_STRING

now = datetime.now(timezone.utc)
expires_at = now + timedelta(seconds=60)

token = jwt.encode(
    {
        'aud': 'groupvan',
        'iss': client_id,
        'kid': key_id,
        'sub': user_id,
        'iat': now,
        'exp': expires_at,
        'type': 'access',
        'jti': str(uuid4()),
        'integration': integration
    },
    private_key,
    algorithm='RS256',
    headers={'gv-ver': 'GV-JWT-V1'}
)

print(token)
const jwt = require('jsonwebtoken');
const { randomUUID } = require('crypto');

const privateKey = YOUR_PRIVATE_KEY; // PEM string
const keyId = YOUR_KEY_ID;
const clientId = YOUR_CLIENT_ID;
const userId = YOUR_USER_ID;
const integration = YOUR_INTEGRATION_STRING;

const nowSeconds = Math.floor(Date.now() / 1000);
const expiresAtSeconds = nowSeconds + 60; // 60 seconds

const payload = {
  aud: 'groupvan',
  iss: clientId,
  kid: keyId,
  sub: userId,
  iat: nowSeconds,
  exp: expiresAtSeconds,
  type: 'access',
  jti: randomUUID(),
  integration: integration
};

const token = jwt.sign(payload, privateKey, {
  algorithm: 'RS256',
  header: { 'gv-ver': 'GV-JWT-V1' }
});

console.log(token);
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

public class JwtExample {
    public static void main(String[] args) throws Exception {
        String privateKeyPem = YOUR_PRIVATE_KEY; // PKCS#8 PEM string
        String keyId = YOUR_KEY_ID;
        String clientId = YOUR_CLIENT_ID;
        String userId = YOUR_USER_ID;
        String integration = YOUR_INTEGRATION_STRING;

        PrivateKey privateKey = loadPrivateKeyFromPem(privateKeyPem);

        Instant now = Instant.now();
        Date iat = Date.from(now);
        Date exp = Date.from(now.plusSeconds(60));

        String token = Jwts.builder()
                .setAudience("groupvan")
                .setIssuer(clientId)
                .setSubject(userId)
                .setIssuedAt(iat)
                .setExpiration(exp)
                .claim("kid", keyId)
                .claim("type", "access")
                .setId(UUID.randomUUID().toString())
                .claim("integration", integration)
                .setHeaderParam("gv-ver", "GV-JWT-V1")
                .signWith(privateKey, SignatureAlgorithm.RS256)
                .compact();

        System.out.println(token);
    }

    private static PrivateKey loadPrivateKeyFromPem(String pem) throws Exception {
        String sanitized = pem
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s", "");
        byte[] keyBytes = Base64.getDecoder().decode(sanitized.getBytes(StandardCharsets.UTF_8));
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(keySpec);
    }
}