REST Authorization from Documentation is not working

Hello everybody

Actually I have two issues.

Issue 1: I can’t run the curl command provided in the documentation (1.5) for basic REST authorization using the JMIX REST API in Windows PowerShell. I am using the following curl:

curl -X POST http://localhost:8080/oauth/token --basic --user client:secret -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&username=admin&password=admin"

I receive the message that parameter “headers” can not be bound and the value “Content-Type: application/x-www-form-urlencoded” of type string can not be converted into type “System.Collections.IDictionary”.

Trying it differently by using samples provided in the forum I implemented the following code:

build.gradle Settings:

    //jmix Security
    implementation 'io.jmix.security:jmix-security-oauth2-starter'
    implementation 'io.jmix.rest:jmix-rest-starter'

application.properties:

# REST oauth2
jmix.security.oauth2.client-id = client
jmix.security.oauth2.client-secret = secret
jmix.security.oauth2.allowed-origins = *

Class RESTManagementFacade:

package io.jmix.bookstore;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpRequest;
import java.net.http.HttpClient;
import java.net.http.HttpResponse;
import java.util.Base64;
import java.util.Map;

@Component
@ManagedResource(description = "JMX bean fuer REST", objectName = "jmix.data:type=RESTBean")
public class RESTManagementFacade {
    @ManagedAttribute(description = "REST size (example attribute)")
    public long getSize() {
        return 0L;
    }

    public void test() {
        authenticate("client", "secret", "admin", "admin");
    }

    private void authenticate(String client, String secret, String username, String password) {
        HttpClient httpClient = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("http://localhost:8080/oauth/token"))
                .header("Authorization", getBasicAuthHeader(client, secret))
                .header("Content-Type", "application/x-www-form-urlencoded")
                .POST(HttpRequest.BodyPublishers.ofString(getAuthRequestBody(username, password)))
                .build();
        try {
            System.out.println("trying to send to httpClient " + request.toString());

            HttpResponse<String> response;
            response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
            System.out.println(response.statusCode());
            if (response.statusCode() == HttpStatus.OK.value()) {
                String responseText = response.body();
                System.out.println("Response: " + responseText);
                // Using Jackson to convert JSON responce to a map:
                Map<String, Object> map = new ObjectMapper().readValue(responseText, Map.class);

                String accessToken = (String) map.get("access_token");
                System.out.println("Access token: " + accessToken);
            } else {
                System.out.println("Error: " + response.statusCode());
            }
        } catch (IOException | InterruptedException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

    private String getBasicAuthHeader(String client, String secret) {
        String str = client + ":" + secret;
        return "Basic " + Base64.getEncoder().encodeToString(str.getBytes());
    }

    private String getAuthRequestBody(String username, String password) {
        return "grant_type=password&username=" + username + "&password=" + password;
    }
}

I am calling the method test() from the main screen of my application as follows:

    @Subscribe("btnRestTestAuthoriziation")
    public void onBtnRestTestAuthoriziationClick(Button.ClickEvent event) {
        try{
            System.out.println("click event fired");
            restManagementFacade.test();
            System.out.println(("restManagementFacade.test() called"));
        }catch (Exception e){
            System.out.println("Error: " + e.getMessage());
            System.out.println(("StackTrace: " + e.getStackTrace().toString()));
        }
    }

This results in “Error 500”.

I am absolutely stucked here. Any hint is highly appreciated.

thx

Michael

I like to add the following finding. In the documentation respectively the automatic settings from the jmix REST plugin the application.properties gain:

jmix.security.oauth2.client-id
jmix.security.oauth2.client-secret

But the description of the JMIX swagger UI states:

"The default client credentials are defined by the following application properties: jmix.security.oauth2.clientId and jmix.security.oauth2.clientSecret"

Which is the correct notation? The one with “-” or the one with “.”?

thx for the clarification

Michael

Do you see any exceptions in the REST server log at this moment?

Both are correct. We switched to “-” notation because IntelliJ Ultimate provides code completion in this case.

thx for that fast answer!

In the Intellj console I do not get any other information. In Postman either. Where Do I find the REST server log in general for a jmix application which is build on a bookstore clone?

best regards, Michael

Hi, it is working now. I am not aware what finally did the trick but here are the changes I made to the application.properties after restarting the engines.

########################################################################################
# JMIX REST-API
########################################################################################
jmix.security.oauth2.client-id = client
jmix.security.oauth2.client-secret = {noop}secret
jmix.security.oauth2.client-authorized-grant-types = password

Please note that I changed the setting for secret to “{noop} secret”. Before I missed the {noop} part.

Thanks for your help and patience.

Best regards

Michael

1 Like