Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 11 HttpClient - Missing form parameter: grant_type

I'm trying to get an access token from Keycloack server via HttpClient of Java 11. But I keep getting an error:

{
    "error":"invalid_request",
    "error_description":"Missing form parameter: grant_type"
}

By the way, with postman, I can get the token. What I'm doing in my code is:

        Map<String, String> values = new HashMap<>() {{
            put("username", username);
            put ("password", password);
            put("grant_type", "password");
        }};

        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper.writerWithDefaultPrettyPrinter()
                .writeValueAsString(values);

        HttpRequest request=HttpRequest.newBuilder()
                .uri(URI.create(tokenEndpoint))
                .setHeader("client_id", clientId)
                .setHeader("client_secret", clientSecret)
                .setHeader("content-type", "application/x-www-form-urlencoded")
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();



        HttpClient.newHttpClient()
                .sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body)
                .thenAccept(System.out::println);

        /*
        //Tried also
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.body());
        */

What am I doing wrong or missing?

Keycloak Missing form parameter: grant_type not worked.

like image 625
PARO Avatar asked Mar 13 '26 05:03

PARO


2 Answers

From the line .setHeader("content-type", "application/x-www-form-urlencoded"), the request is expecting form data, but you are sending json in the request body (via ObjectMapper.writeValueAsString()).

If you are trying to send form data, then this should be the correct encoding:

String requestBody = "username=" + username + "password=" + password + "grant_type=password"

If the API is expecting JSON, then change the content type header to application/json:

HttpRequest request=HttpRequest.newBuilder()
    ...
    .setHeader("content-type", "application/json")
    ...
like image 120
rusheb Avatar answered Mar 16 '26 12:03

rusheb


This is how we done login:

MultiValueMap<String, String> requestParams = new LinkedMultiValueMap<>();
requestParams.add("client_id", keycloakProperties.getResource());
requestParams.add("username", username);
requestParams.add("password", password);
requestParams.add("grant_type", "password");
requestParams.add("client_secret", String.valueOf(keycloakProperties.getCredentials().get("secret")));
requestParams.add("scope", "openid");

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestParams, headers);

String url = keycloakProperties.getAuthServerUrl() + "/realms/" + keycloakProperties.getRealm() + "/protocol/openid-connect/token";

AccessTokenResponse keycloakAccessToken = getAccessTokenResponse(request, url);


// sometimes SSL handshake was failing, so catching error and trying again :)
private AccessTokenResponse getAccessTokenResponse(HttpEntity<MultiValueMap<String, String>> request, String url) {
    try {
        ResponseEntity<AccessTokenResponse> response = restTemplate.postForEntity(url, request, AccessTokenResponse.class);
        return response.getBody();
    } catch (ResourceAccessException e) {
        log.error("KeyCloak getAccessTokenResponse: " + e.getMessage());
        try {
            ResponseEntity<AccessTokenResponse> response = restTemplate.postForEntity(url, request, AccessTokenResponse.class);
            return response.getBody();
        } catch (Exception ex) {
            throw ex;
        }
    } catch (Exception e) {
        throw e;
    }
}
like image 21
Dmitri Algazin Avatar answered Mar 16 '26 11:03

Dmitri Algazin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!