0

I'm looking for refresh token by using the Java Admin Client https://github.com/keycloak/keycloak/tree/master/integration/admin-client

Cannot find anything about it

Regards

EDIT :

finally I go that :

public AccessTokenResponse executeRefresh(String refreshToken) {
    String url = "https://url/auth" + "/realms/" + keycloakRealm + "/protocol/openid-connect/token";
    Configuration kcConfig = new Configuration(authServerUrl, keycloakRealm, keycloakInternalClientId, null, null);
    Http http = new Http(kcConfig, (params, headers) -> {
    });
    return http.<AccessTokenResponse>post(url)
            .authentication()
            .client()
            .form()
            .param("grant_type", "refresh_token")
            .param("refresh_token", refreshToken)
            .param("client_id", keycloakInternalClientId)
            .param("client_secret", keycloakInternalClientSecret)
            .response()
            .json(AccessTokenResponse.class)
            .execute();
}
Maryo
  • 483
  • 2
  • 13
  • 25

4 Answers4

0

org.keycloak.admin.client.Keycloak.tokenManager().refreshToken() can refresh token. For example:

// Create a Keycloak client
Keycloak kc = KeycloakBuilder.builder()
        .serverUrl("http://localhost:8080/auth")
        .realm("master")
        .username("admin")
        .password("password")
        .clientId("admin-cli")
        .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build())
        .build();

TokenManager tokenManager = kc.tokenManager();
// get access token
AccessTokenResponse accessTokenResponse = tokenManager.getAccessToken();
System.out.println(accessTokenResponse.getRefreshToken());
// Refresh token
accessTokenResponse = tokenManager.refreshToken();
System.out.println(accessTokenResponse.getRefreshToken());
Kohei TAMURA
  • 4,970
  • 7
  • 25
  • 49
  • 1
    Hello. The problem the UI don't keep the password, it send refresh token when token expire. So I only have the username and refresh token. I don't find anything in keycloak java client for that. – Maryo Aug 27 '19 at 08:47
0

Sadly Java Admin Client does not have this kind of functionality (hopefully will have in the future)

For now, look at this answer: Refresh access_token via refresh_token in Keycloak

Vanley
  • 121
  • 1
  • 2
0

Have achieved it through RestTemplate inside my spring-boot application.

Below is the code I have used to get refresh token :-

public ResponseEntity<RefreshTokenResponse> refreshToken(String refreshToken) {
    String url = authUrl+ "/realms/" + realm + "/protocol/openid-connect/token";
    RestTemplate restTemplate = new RestTemplate();

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

    MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
    map.add("grant_type", "refresh_token");
    map.add("refresh_token", refreshToken);
    map.add("client_id", clientId);
    map.add("client_secret", clientSecret);

    HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);

    ResponseEntity response =
            restTemplate.exchange(url,
                    HttpMethod.POST,
                    entity,
                    Object.class);
    return response;}

RefreshTokenResponse :-

    @Data
public class RefreshTokenResponse {
    private AccessTokenResponse token;
}

Keycloak v19.0.0

authUrl :- where keycloak server is running. my case http://localhost:8080/

ream :- your realm name

Ayush Sharma
  • 69
  • 2
  • 5
0

Actually, I managed to make Keycloak client do this job for me after spending some time with the issue. In my case I had to connect to a Keycloak server with password grant type, and use access token to fetch data from a third party protected endpoint in a Spring Boot server side application.

At the end I came up with a service, which provides an access token after initial authentication, and automatic refresh/re-authentication on demand.

I added a @Configuration bean, which contained the connection parameters to the third party Keycloak instance:

    package no.currentclient.application.api.config;  // real package name masked

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    @Configuration
    public class OauthClientConfig {

        public record OauthConfig(String realm, String authServerUrl, String clientId, String username, String password) {
        }

        @Bean
        OauthConfig oauthConfig(
                @Value("${client.oauth.realm}") String realm,
                @Value("${client.oauth.auth-server-url}") String authServerUrl,
                @Value("${client.oauth.resource}") String clientId,
                @Value("${client.oauth.username}") String username,
                @Value("${client.oauth.password}") String password
        ) {
            return new OauthConfig(realm,
                    authServerUrl,
                    clientId,
                    username,
                    password);
        }
    }

After I created a Spring Service which is capable of authenticating, getting and refreshing an access token:

package no.currentclient.application.auth.oauthclient;  // real package name masked

import com.fasterxml.jackson.databind.ObjectMapper;
import no.currentclient.application.api.config.OauthClientConfig;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.keycloak.authorization.client.representation.ServerConfiguration;
import org.keycloak.authorization.client.util.Http;
import org.keycloak.authorization.client.util.TokenCallable;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Collections;

@Service
public class OauthTokenService {

    private final TokenCallable tokenCallable;

    public OauthTokenService(
            OauthClientConfig.OauthConfig oauthConfig,
            OkHttpClient okHttpClient
    ) throws IOException {
        var serverConfiguration = getServerConfiguration(oauthConfig.authServerUrl()+"/auth/realms/"+oauthConfig.realm()+"/.well-known/openid-configuration", okHttpClient);
        var config = new org.keycloak.authorization.client.Configuration(
                // These might all be set to null -> only tokenMinimumTimeToLive is used in TokenCallable...
                null,null,null, null,null);
        var http = new Http(config, (requestParams, requestHeaders) -> requestParams.put("client_id", Collections.singletonList("deichman")));

        tokenCallable = new TokenCallable(oauthConfig.username(), oauthConfig.password(), http, config, serverConfiguration);
    }

    /*
    * Call this method to get hold of an on-demand refreshed auth token. TokenCallable handles the burden of token
    * refresh and re-authentication in case of session timeout.
    */
    public String getAccessToken() {
        return tokenCallable.call();
    }

    private ServerConfiguration getServerConfiguration(String configUrl, OkHttpClient okHttpClient) throws IOException {
        var configRequest = new Request.Builder().url(configUrl).get().build();
        try (var response = okHttpClient.newCall(configRequest).execute()) {
            return new ObjectMapper().readValue(response.body().string(), ServerConfiguration.class);
        }
    }
}

TokenCallable hides all the complexity of refresh/re-authentication on demand.

Hope it helps a few struggling with this problem.