【问题标题】:Spring Security OAuth 2.0 with no client_secret没有 client_secret 的 Spring Security OAuth 2.0
【发布时间】:2015-12-29 15:58:28
【问题描述】:

我正在使用 Spring Boot 和 Spring Security OAuth 2.0 为我的 Android 应用程序开发登录系统。

我的起点是以下演示存储库:https://github.com/royclarkson/spring-rest-service-oauth。在演示中,您可以找到以下设置:

OAuth2 客户端:

clients
    .inMemory()
        .withClient("clientapp")
            .authorizedGrantTypes("password", "refresh_token")
            .authorities("USER")
            .scopes("read", "write")
            .resourceIds(RESOURCE_ID)
            .secret("123456");

在其测试中获取访问令牌的方法:

private String getAccessToken(String username, String password) throws Exception {
    String authorization = "Basic " + new String(Base64Utils.encode("clientapp:123456".getBytes()));

    String content = mvc
        .perform(
                post("/oauth/token")
                        .header("Authorization", authorization)
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                        .param("username", username)
                        .param("password", password)
                        .param("grant_type", "password")
                        .param("scope", "read write")
                        .param("client_id", "clientapp")
                        .param("client_secret", "123456"))
        .andExpect(status().isOk())
        .andReturn().getResponse().getContentAsString();

    return content.substring(17, 53);
}

项目中的每个测试都提供了完美的工作,但我想以不同的方式做事,但我在这样做时遇到了麻烦。如您所见,演示客户端定义了一个client_secret(也用于测试),但client_secret 在Android 环境中确实毫无价值,我不能保证它的“隐私性”。

见https://apigility.org/documentation/auth/authentication-oauth2:

如果我们使用的是公共客户端(默认情况下,当没有秘密与客户端相关联时为真),您可以省略 client_secret 值;

看看https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-31#section-2.1:

公开: 客户无法为其保密 凭据(例如,客户端在使用的设备上执行 资源所有者,例如已安装的本机应用程序或 Web 基于浏览器的应用程序),并且无法提供安全客户端 通过任何其他方式进行身份验证。

所以我所做的是删除客户端配置中的秘密:

clients
    .inMemory()
        .withClient("books_password_client")
        .authorizedGrantTypes("password", "refresh_token")
        .authorities("USER")
        .scopes("read", "write")
        .resourceIds(RESOURCE_ID);

还改编了getAccessToken(...)方法:

private String getAccessToken(String username, String password) throws Exception {
    String authorization = "Basic " + new String(Base64Utils.encode("books_password_client:123456".getBytes()));

    String content = mvc
        .perform(
                post("/oauth/token")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                        .param("username", username)
                        .param("password", password)
                        .param("grant_type", "password")
                        .param("client_id", "books_password_client"))
        .andExpect(status().isOk())
        .andReturn().getResponse().getContentAsString();

    return content.substring(17, 53);}
}

但是当我使用这个新设置时,我的测试失败了,我无法获得访问令牌,我不断收到 HTTP 错误 401 Unauthorized。

【问题讨论】:

  • 你能解决这个问题吗?我正在为 Web 客户端制作 API,让这样的客户端发送 client_id 和 client_secret 也没有意义。你有没有想出一个不需要这个的方法?
  • 不,我没有,客户端的秘密对我来说仍然很奇怪:S
  • 是的,我也一样 XD 如果你落后了,请告诉我^^
  • 我会:D,你也一样!

标签: java spring-boot spring-security-oauth2


【解决方案1】:

这就是我的工作:

Response response =
    given().
        auth()
            .preemptive().basic("clientapp", "")
            .formParam("username", username)
            .formParam("password", password)
            .formParam("grant_type", "password")
            .formParam("scope", "read%20write")
    when()
        .post("/oauth/token").
    then()
        .extract().response();

【讨论】:

    猜你喜欢
    • 2014-05-11
    • 2016-09-09
    • 2014-04-06
    • 1970-01-01
    • 2017-03-31
    • 2018-01-24
    • 2019-05-24
    • 2011-06-06
    • 2017-01-05
    相关资源
    最近更新 更多