> ## Documentation Index
> Fetch the complete documentation index at: https://developer.utgl.io/llms.txt
> Use this file to discover all available pages before exploring further.

# How to authenticate with the Issuing API using Java

## Overview

This tutorial shows you how to authenticate to the Issuing API using Java by generating signed JSON Web Tokens (JWTs).

## In This Recipe

1. Add Dependencies
2. Create AccessTokenSigner
3. Usage - GET Request
4. Usage - POST Request

## Prerequisites

* Java 8 or higher
* Your Issuing API credentials (Access Key and RSA key pair)
* Maven or Gradle for dependency management

## Step 1: Add Dependencies

Add these dependencies to your `pom.xml`:

```xml theme={null}
<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>
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>
```

## Step 2: Create AccessTokenSigner

Create a utility class to handle JWT signing with SHA256 body hashing:

```java theme={null}
package com.example;

import java.time.Instant;
import java.util.Date;
import java.util.Base64;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.digest.DigestUtils;

public class AccessTokenSigner {
  public static String signJWT(
      String privateKey, 
      String accessKey, 
      String uri, 
      String method, 
      String requestBody) throws Exception {
    
    // Private key should be Base64-encoded with no headers/footers/newlines
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
        Base64.getDecoder().decode(privateKey)
    );
    PrivateKey privKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
    
    Instant now = Instant.now();
    Date issuedAt = Date.from(now);
    Date expiration = Date.from(now.plusSeconds(30)); // 30 second expiration
    
    // Hash request body with SHA256
    String hashedBody = DigestUtils.sha256Hex(requestBody);
    
    String jws = Jwts.builder()
        .setHeaderParam("typ", "JWT")
        .setSubject(accessKey)
        .setExpiration(expiration)
        .setIssuedAt(issuedAt)
        .claim("uri", uri)
        .claim("method", method)
        .claim("body", hashedBody)
        .signWith(privKey, SignatureAlgorithm.RS256)
        .compact();
    
    return jws;
  }
}
```

### Important Notes:

* **Request body is hashed** with SHA256 before signing
* **30 second expiration** for security
* **Private key format**: Base64-encoded PKCS8, no PEM headers/footers
* **Empty body**: Use empty string `""` for GET requests

## Step 3: Usage - GET Request

Make a simple GET request to test connectivity:

```java theme={null}
import com.nimbusds.jose.JOSEException;

public class ExampleAPI {
    public static void main(String[] args) {
        String privateKey = "<RSA private key>"; // Replace with actual private key
        String accessKey = "<access key>"; // Replace with actual access key
        String uri = "/v1/ping";
        String method = "GET";
        String requestBody = "";
        try {
            String jwt = AccessTokenSigner.signJWT(privateKey, accessKey, uri, method, requestBody);
            // Use the JWT in the Authorization header of the HTTP request
            String authorizationHeader = "Bearer " + jwt;
            // Make the HTTP request to the API endpoint
            // ...
        } catch (JOSEException e) {
            // Handle JOSEException
        }
    }
}
```

<Note>
  This example shows JWT generation only. Use your preferred HTTP client (Apache HttpClient, OkHttp, Spring RestTemplate, etc.) to make the actual API request with the `authorizationHeader`.
</Note>

## Step 4: Usage - POST Request

Make a POST request with a request body:

```java theme={null}
import com.nimbusds.jose.JOSEException;

public class ExampleAPI {
    public static void main(String[] args) {
        String privateKey = "<RSA private key>"; // Replace with actual private key
        String accessKey = "<access key>"; // Replace with actual access key
        String uri = "/v1/ping";
        String method = "POST";
        String requestBody = "{'message': 'Hello, world!'}"; // Replace with actual request body

        try {
            String jwt = AccessTokenSigner.signJWT(privateKey, accessKey, uri, method, requestBody);
            // Use the JWT in the Authorization header of the HTTP request
            String authorizationHeader = "Bearer " + jwt;
            // Make the HTTP request to the API endpoint
            // ...
        } catch (JOSEException e) {
            // Handle JOSEException
        }
    }
}
```

## Common Pitfalls

<Warning>
  **Body Hashing is Critical!** The `AccessTokenSigner` automatically hashes the request body with SHA256 before including it in the JWT claims. Make sure you pass the **exact same request body** to both `signJWT()` and your HTTP client.
</Warning>

<Tip>
  **Token Expiration**: JWT tokens expire after 30 seconds. Generate a fresh token for each API request to avoid authentication errors.
</Tip>

## Next Steps

* See [Authentication](/issuing/getting-started/authentication) for more details on JWT signing
* Explore [API Endpoints](/api-reference) to see what you can do
* Check out [Request Signing](/issuing/getting-started/request-signing) for security best practices
