Spring集成Keycloak获取令牌时redirect_uri错误400问题
问题分析与解决方案
核心问题定位
报错invalid_grant: Incorrect redirect_uri的关键原因是Spring代码中传入的redirect_uri与授权请求时使用的redirect_uri不完全一致,或是代码生成的URI存在多余格式(比如带空查询参数),导致Keycloak校验不通过。
具体修复步骤
统一redirect_uri格式
直接用字符串常量传入redirect_uri,避免UriComponentsBuilder.build()可能生成的多余格式(比如带空?后缀):map.add("redirect_uri", "http://127.0.0.1:3002/callback");校验授权请求与回调的URI一致性
确保用户跳转到Keycloak授权页面时携带的redirect_uri,和回调代码中传入的完全一致——包括协议、主机、端口、路径,localhost和127.0.0.1会被视为不同地址,末尾也不能多带斜杠。验证请求参数匹配度
在catch块中打印完整请求参数,对比Postman的参数是否完全一致:catch (Exception e) { System.out.println(e.getMessage()); System.out.println("实际发送参数: " + map.toString()); }重点确认
client_secret为空的配置是否和Keycloak客户端类型匹配(public类型客户端无需secret)。检查Keycloak客户端配置
确认客户端的Valid Redirect URIs列表包含http://127.0.0.1:3002/callback,可使用通配符http://127.0.0.1:3002/*放宽匹配范围。
修复后完整代码示例
@GetMapping("/callback") @ResponseBody public String getToken(@RequestParam String code) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED.toString()); MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); map.add("code", code); map.add("client_id", "spring-login-app"); map.add("client_secret", ""); map.add("grant_type", "authorization_code"); map.add("redirect_uri", "http://127.0.0.1:3002/callback"); HttpEntity formEntity = new HttpEntity<>(map, headers); try { ResponseEntity<KeycloakTokenResponse> response = restTemplate.exchange("http://127.0.0.1:8080/auth/realms/raroc/protocol/openid-connect/token", HttpMethod.POST, formEntity, KeycloakTokenResponse.class); KeycloakTokenResponse resp = response.getBody(); return resp.getAccess_token(); } catch (Exception e) { System.out.println(e.getMessage()); System.out.println("实际发送参数: " + map.toString()); } return "nothing"; }
内容的提问来源于stack exchange,提问作者Titrofkek
相关产品推荐
相关产品推荐

