当我尝试通过 keycloak 调用我的安全 API 时收到状态 401 Unauthorized

Posted

技术标签:

【中文标题】当我尝试通过 keycloak 调用我的安全 API 时收到状态 401 Unauthorized【英文标题】:I am receiving status 401 Unauthorized when I attempt to call my secured API by keycloak 【发布时间】:2021-01-20 05:15:00 【问题描述】:

我有一个提供 REST API 端点的 Web 应用程序,由 Spring Security 和 SSO Keycloak 保护。

我的 Web 应用程序在启用保护的情况下工作正常,我可以使用 Web 浏览器访问 REST API 端点,在 keycloak 上进行身份验证并重定向回端点后。我收到了预期的 JSON 响应,这意味着应该正确配置用户和角色。

但是当我想从另一个 Web 应用程序或使用 Postman 调用提供的 REST API 端点时,我每次都会遇到错误 401 错误:未授权。

在我提出的请求的标题中: “授权”:“承载 eyJhbGciOiJSUzI1NiIsInR5cCIgO....”令牌。

我能够从消费者 Web 应用程序中的 keycloak 以及当我使用邮递员发出请求时获取此令牌。

我的 Spring Security 配置中的 Keycloak 配置:

@KeycloakConfiguration
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter 
    /**
     * Registers the KeycloakAuthenticationProvider with the authentication manager.
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) 
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    

    /**
     * Defines the session authentication strategy.
     */
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() 
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        super.configure(http);
        http
                .authorizeRequests()
                .antMatchers("/api/v1/**").hasRole("USER")
                .antMatchers("/admin/**", "/app/**").hasRole("ADMIN")
                .anyRequest().permitAll();
    

我的 keycloak.json 文件:


    "realm": "realm-name",
    "auth-server-url": "https://auth.server.com/auth/",
    "ssl-required": "external",
    "resource": "resource-name",
    "verify-token-audience": true,
    "credentials": 
        "secret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    ,
    "use-resource-role-mappings": true,
    "confidential-port": 0

我在api控制器中的方法:

@RestController
@RequestMapping("/api/v1")
public class WakeMeUpController 

    @RequestMapping(value = "/test", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE)
    public String testMeUp() 
        return "I am tested!";
    

这是我在 keycloak 中的客户端配置的一部分: keycloak Client screen

Rest keycloak 配置是默认的。

感谢您的帮助!

【问题讨论】:

将此添加到您的应用属性:logging.level.org.springframework.security=DEBUG 并在获得 401 后粘贴您的日志输出。 谢谢!这让我明白了这个问题,我能够解决它。 【参考方案1】:

谢谢。问题在于 keycloak 中的受众配置。

对于客户端,您需要在 Client -> -> Mappers 下配置新的映射并添加另一个映射器类型为“Audience”和适当的“Included Client Audience”的映射(我选择我用来制作的客户端 ID请求)

解决这个问题后我还面临的另一个问题是,用户已通过身份验证,但被禁止访问端点。 将角色显式添加到客户端配置本身并将此角色分配给用户解决它并且它正在工作。

从巨大的帮助下,将 Spring 日志记录设置为 DEBUG logging.level.org.springframework.security=DEBUG

还有服务器响应中的 XXX-Authentication 标头,可以更好地描述问题所在。

【讨论】:

由于"verify-token-audience": true"use-resource-role-mappings": true 设置,需要您进行修复。首先负责检查aud jwt 声明是否包含您的<client-id>。第二个设置负责根据resource_access.<client-id>.roles jwt 声明解析您的用户角色。出于安全原因,建议在适配器配置中使用这两种设置。

以上是关于当我尝试通过 keycloak 调用我的安全 API 时收到状态 401 Unauthorized的主要内容,如果未能解决你的问题,请参考以下文章

Spring base rest apis 的 Keycloak 安全性

Keycloak - 将用户与 LDAP 同步的问题

keycloak API 出现 403 错误

Keycloak变更注册流程/创建用户API

具有授权的 Keycloak 自定义 SPI REST 端点

Keycloak + Spring Security,通过本地登录表单