Skip to content

Wrong Content-Type in C++ and Python Client for Keycloak Oauth2 Tokens. #8972

@cuzyoucant

Description

@cuzyoucant

Describe the bug
When using Keycloak as Oauth2 provider you cannot get any Tokens via the C++ and Python client due to the missmatch in Content-Type.
The C++/python client sends the POST to the token-endpoint with Content-Type "application/json" but keycloak only supports/allows the content-type "application/x-www-form-urlencoded" and you will get a 400 Bad Request error because the credentials like client-id and client secret are missing.

Error on Python side:
2020-12-16 14:12:10.835 ERROR [140634212321088] AuthOauth2:312 | Response failed for issuerurl https://mysite.com/auth/realms/myrealm/.well-known/openid-configuration. response Code 400 passedin: { "grant_type": "client_credentials", "client_id": "my-client-id", "client_secret": "my-secret", "audience": "my-audience" }
Note: The error is a but wrong because it prints the wrong URL. The client can get the token-endpoit url just finde via the .well-known url. The error arises when it wants to get a token.

To Reproduce

  1. Download Keycloak standalone and setup a Client.
  2. Download and setup python + pulsar python client.
  3. Try to get a token with the python-client (small code below)

python code:
`creds = {
"grant_type": "client_credentials",
"client_id": "my-client-id",
"client_secret": "my-secret",
"issuer_url": "https://myurl.ai/auth/realms/myrealm",
"audience": "my-audience",
}
client = pulsar.Client(
"pulsar+ssl://localhost:6651",
use_tls=True,
tls_trust_certs_file_path="my-cert.crt",
authentication=AuthenticationOauth2(json.dumps(creds)),
)

my_topic = "test-topic"
producer = client.create_producer(topic=my_topic, send_timeout_millis=20000)`

Expected behavior
The python client should be able the get a token and authenticate with the pulsar broker.

Desktop (please complete the following information):

  • OS: Ubuntu 19.10
  • Pulsar cluster and python client: 2.7
  • keycloak: 10.3

Additional context
I made a small change in the C++ Client code to get it to work for now. The optimal solution would be that you can choose via the AuthenticationOauth2 class in python which content-type you want to send the POST in.

Changes made in pulsar-client-cpp/lib/auth/AuthOauth2.cc in function Oauth2TokenResultPtr ClientCredentialFlow::authenticate():

First change content-type to application/x-www-form-urlencoded.
list = curl_slist_append(list, "Content-Type: application/x-www-form-urlencoded");

Then we need to add the client credential parameters to the POST:
Note: As you can see i commented out the part with the Json-parameters and built the string on my own. I am sure there are way better solutions but i just wanted to get it to work for now.

   // fill in the request data
    // boost::property_tree::ptree pt;
    // pt.put("grant_type", "client_credentials");
    // pt.put("client_id", clientId_);
    // pt.put("client_secret", clientSecret_);
    // pt.put("audience", audience_);
    //boost::property_tree::json_parser::write_json(ss, pt);


std::stringstream ss;
ss << "grant_type" << "=" << "client_credentials" << "&" << "client_id" << "=" << clientId_ << "&" << "client_secret" << "=" << clientSecret_ << "&" << "audience" << "=" << audience_;

    std::string ssString = ss.str();

    curl_easy_setopt(handle, CURLOPT_POSTFIELDS, ssString.c_str());

The rest is the same.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions