Spring Boot 如何使用Java客户端刷新令牌?

gab6jxml  于 2022-11-23  发布在  Spring
关注(0)|答案(4)|浏览(184)

我正在使用Java管理客户端https://github.com/keycloak/keycloak/tree/master/integration/admin-client查找刷新标记
找不到任何相关信息
此致
编辑:
最后我说:

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();
}
mjqavswn

mjqavswn1#

org.keycloak.admin.client.Keycloak.tokenManager().refreshToken()可以刷新令牌。例如:

// 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());
v09wglhw

v09wglhw2#

遗憾的是,Java管理客户端没有这种功能(希望将来会有)
现在,看看这个答案:Refresh access_token via refresh_token in Keycloak

aij0ehis

aij0ehis3#

我已经通过我的spring-boot应用程序中的RestTemplate实现了它。
下面是我用来获取刷新令牌的代码:-

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;}

刷新令牌响应:-

@Data
public class RefreshTokenResponse {
    private AccessTokenResponse token;
}

密钥隐藏v19.0.0
authUrl:-keycloak服务器正在运行的位置。我的案例http://localhost:8080/
ream:-您的域名

13z8s7eq

13z8s7eq4#

实际上,在花了一些时间处理这个问题之后,我设法让Keycloak客户端为我完成了这项工作。在我的情况下,我必须连接到一个带有密码授权类型的Keycloak服务器,并使用访问令牌从Sping Boot 服务器端应用程序中的第三方受保护端点获取数据。
最后,我提出了一个服务,它在初始身份验证后提供一个访问令牌,并根据需要自动刷新/重新身份验证。
我添加了一个@Configuration bean,它包含到第三方Keycloak示例的连接参数:

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);
        }
    }

在我创建了一个能够进行身份验证、获取和刷新访问令牌的Spring Service之后:

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隐藏了按需刷新/重新验证的所有复杂性。
希望它能帮助一些在这个问题上挣扎的人。

相关问题