HTTP Client for Keycloak using OpenID Connect

In modern web applications, authentication and authorization are critical components. Keycloak is a powerful open-source identity and access management solution for modern applications and services. This article will guide you through creating a Java HTTP client to test OpenID Connect token authentication with Keycloak, and we will also demonstrate the equivalent steps using curl.

Prerequisites

  • A running Keycloak instance.
  • A Keycloak realm and client configuration.
  • Java Development Kit (JDK) 11 or later.
  • Basic knowledge of Java programming.

If you are new to Keycloak, we recommend checking this article: Getting started with Keycloak powered by Quarkus

Setting Up Keycloak

Before diving into the Java code, ensure you have a Keycloak server running and a realm configured with a client and user. Here are the steps:

1 – Install Keycloak: Download and run the Keycloak server from the official Keycloak website.

2 – Create a Realm: Log in to the Keycloak admin console, create a new realm. In our example we will be using the realm ApplicationRealm.

keycloak http client test

3 – Create a Client: Within the ApplicationRealm, create a new client. Our example uses the Client my-client.

how to test keycloak

4 – Create Users: Add some users to your Realm. For example, we will use the user1 with a password (123456).

keycloak how to fetch the jwt token

Java HTTP Client for Keycloak

Step 1: Add Dependencies

Ensure you have the following dependencies in your pom.xml for a Maven project:

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.13.3</version>
    </dependency>
</dependencies>

Step 2: Write the Java Client

Here’s a Java application that sends a POST request to obtain a JWT token from Keycloak and then uses that token to access a protected endpoint.

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class SimplePostRequest {

    public static void main(String[] args) {
        String tokenUrl = "http://localhost:8080/realms/ApplicationRealm/protocol/openid-connect/token";
        String apiUrl = "http://localhost:8081/api/admin";

        String grantType = "password";
        String clientId = "my-client";
        String username = "user1";
        String password = "123456";

        try {
            // Prepare form data
            Map<Object, Object> data = new HashMap<>();
            data.put("grant_type", grantType);
            data.put("client_id", clientId);
            data.put("username", username);
            data.put("password", password);

            String form = data.entrySet()
                    .stream()
                    .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8))
                    .collect(Collectors.joining("&"));

            // Create HttpClient
            HttpClient client = HttpClient.newHttpClient();

            // Create HttpRequest for POST to get the token
            HttpRequest tokenRequest = HttpRequest.newBuilder()
                    .uri(URI.create(tokenUrl))
                    .header("Content-Type", "application/x-www-form-urlencoded")
                    .POST(HttpRequest.BodyPublishers.ofString(form))
                    .build();

            // Send the POST request
            HttpResponse<String> tokenResponse = client.send(tokenRequest, HttpResponse.BodyHandlers.ofString());
            System.out.println("POST Response Code :: " + tokenResponse.statusCode());

            if (tokenResponse.statusCode() == 200) { // success
                String responseBody = tokenResponse.body();
                System.out.println("Response Body: " + responseBody);

                // Parse JSON response
                ObjectMapper mapper = new ObjectMapper();
                JsonNode rootNode = mapper.readTree(responseBody);
                JsonNode accessTokenNode = rootNode.path("access_token");
                String token = accessTokenNode.asText();

                if (!accessTokenNode.isMissingNode()) {
                    System.out.println("Access Token: " + token);

                    // Create HttpRequest for GET to access the secured endpoint
                    HttpRequest apiRequest = HttpRequest.newBuilder()
                            .uri(URI.create(apiUrl))
                            .header("Authorization", "Bearer " + token)
                            .GET()
                            .build();

                    // Send the GET request
                    HttpResponse<String> apiResponse = client.send(apiRequest, HttpResponse.BodyHandlers.ofString());
                    System.out.println("GET Response Code :: " + apiResponse.statusCode());

                    if (apiResponse.statusCode() == 200) { // success
                        System.out.println("GET Response: " + apiResponse.body());
                    } else {
                        System.out.println("GET request not worked");
                        System.out.println("Error Response: " + apiResponse.body());
                    }
                } else {
                    System.out.println("Response: " + responseBody);
                }
            } else {
                System.out.println("POST request not worked");
                System.out.println("Error Response: " + tokenResponse.body());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Explanation

  1. Sending POST Request for Token:
    • Prepare the form data for the POST request.
    • Send the POST request to Keycloak to obtain the OpenID Connect token.
    • Parse the JSON response to extract the token.
  2. Using the Token for Authenticated Request:
    • Create a GET request to the protected endpoint, setting the Authorization header with the Bearer token.
    • Send the GET request and print the response.

Testing with curl

You can achieve the same results using curl. Here are the steps:

Step 1: Obtain the Token

curl -X POST "http://localhost:8080/realms/ApplicationRealm/protocol/openid-connect/token" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=password" \
     -d "client_id=my-client" \
     -d "username=user1" \
     -d "password=123456"

The response will include the access_token.

Step 2: Access the API Endpoint

curl -H "Authorization: Bearer <access_token>" "http://localhost:8081/api/admin"

Replace <access_token> with the token obtained from the previous step.

Conclusion

In this article, we demonstrated how to create a Java HTTP client to interact with Keycloak for OpenID Connect token authentication and access a protected endpoint. We also showed the equivalent steps using curl. This guide should help you understand the process of testing OpenID Connect token authentication with Keycloak in your Java applications.