Hi, everyone,
Currenty, I’m using keycloak 11.0.2 and using keycloak-authz-client with the same version to request offline tokens. Everything is working fine with this code:
public static String getOfflineToken() {
Map<String, Object> clientCredentials = new LinkedHashMap<>();
clientCredentials.put("secret", "V4bbMDkQCqn1k9h7fon78KcYMBA8ifmD");
clientCredentials.put("grant_type", "client_credential");**
Configuration configuration =
new Configuration("http://localhost:8080", "universidade", "lyceum-api", clientCredentials, null);
AuthzClient authzClient = AuthzClient.create(configuration);
AuthorizationRequest request = new AuthorizationRequest();
request.setScope("offline_access");
AuthorizationResponse response = authzClient.authorization().authorize(request);
return response.getToken();
}
Note: The realm and client configuration meet the keycloak specification for offline access: Offline Access | keycloak-documentation
Recently, I’ve upgraded the version of keycloak and authz to 17.0.0, without change the realm and client configurations. After that, the request code only returns tokens without offline_access scope.
Looking at the logs, it’s possible to see the request:
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> POST /realms/universidade/protocol/openid-connect/token HTTP/1.1
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Authorization: Basic bHljZXVtLWFwaTpWNGJiTURrUUNxbjFrOWg3Zm9uNzhLY1lNQkE4aWZtRA==
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Length: 105
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Type: application/x-www-form-urlencoded; charset=UTF-8
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Host: localhost:8080
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.13 (Java/15.0.2)
10:09:29.893 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
10:09:29.893 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /realms/universidade/protocol/openid-connect/token HTTP/1.1[\r][\n]"
10:09:29.893 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Authorization: Basic bHljZXVtLWFwaTpWNGJiTURrUUNxbjFrOWg3Zm9uNzhLY1lNQkE4aWZtRA==[\r][\n]"
10:09:29.893 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Length: 105[\r][\n]"
10:09:29.893 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded; charset=UTF-8[\r][\n]"
10:09:29.898 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Host: localhost:8080[\r][\n]"
10:09:29.898 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
10:09:29.898 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.13 (Java/15.0.2)[\r][\n]"
10:09:29.898 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
10:09:29.898 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
10:09:29.898 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "audience=lyceum-api&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Auma-ticket&scope=offline_access"
10:09:30.451 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 200 OK[\r][\n]"
Note that the ‘scope=offline_access’ parameter is present.
What caught my attention was the grant-type parameter, I expected it should has ‘client_credentials’ value.
With that in mind, i inspected the authz code and found something interesting. In some point of the authtorization request, the authz sets the grant_type to client_credentials, but right after that it changes to other value.
See bellow the code of the class HttpMethodAuthenticator where that happens:
public HttpMethod<R> uma() {
// if there is an authorization bearer header authenticate using bearer token
Header authorizationHeader = method.builder.getFirstHeader("Authorization");
if (!(authorizationHeader != null && authorizationHeader.getValue().toLowerCase().startsWith("bearer"))) {
client();
}
method.params.put(OAuth2Constants.GRANT_TYPE, Arrays.asList(OAuth2Constants.UMA_GRANT_TYPE));**
return method;
}
Also, se the code of the method client():
public HttpMethod<R> client() {
this.method.params.put(OAuth2Constants.GRANT_TYPE, Arrays.asList(OAuth2Constants.CLIENT_CREDENTIALS));
authenticator.configureClientCredentials(this.method.params, this.method.headers);
return this.method;
}
It seems that there is something wrong in those steps.
Somebody has any idea what i need to change on the code or configuration to obtain offline tokens in keycloak 17.0.0 using authz.