【问题标题】:OAuth2 requesting token returns 401OAuth2 请求令牌返回 401
【发布时间】:2016-08-11 22:42:40
【问题描述】:

我正在尝试对使用 OAuth2 的站点进行身份验证并将令牌存储在我的会话对象中。我的网络应用程序最初检查是否已经存在令牌,如果没有,它将用户重定向到外部站点上的登录页面,用户登录并被重定向回我的应用程序。到目前为止,一切都很好,这行得通。我的应用程序将我定向到外部站点 (Mendeley),我在那里登录,然后它将我重定向回我期望它访问的应用程序中的 url。

当它重定向回我的应用程序时,我希望请求中有一个 code 和一个 state 参数,我确实看到了这些,所以我假设我在正确的轨道(如果我错了就阻止我)。那么,如果我理解正确的话,我应该将 代码 发布回 Mendeley 服务以获取我的授权令牌,而这一切都发生了。

URL url = new URL("https://api-oauth2.mendeley.com/oauth/token");
HttpsURLConnection connection = (HttpsURLConnection) url
        .openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
    "application/x-www-form-urlencoded");

        String authString = getClientId() + ":" + "[MY CLIENT SECRET]";
        System.out.println("auth string: " + authString);
        byte[] authEncBytes = Base64.getUrlEncoder().encode(
                authString.getBytes());
        String authStringEnc = new String(authEncBytes);
        System.out.println("Base64 encoded auth string: " + authStringEnc);

        connection.addRequestProperty("Authorization", "Basic "
                + authStringEnc);

connection.setDoOutput(true);
OutputStream os = connection.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(os);
writer.write("scope=all&grant_type=authorization_code");
writer.write("&client_id=");
writer.write(getClientId());
writer.write("&code=");
writer.write(code);
writer.write("&redirect_uri=");
writer.write(getMendeleyRedirectUrl(request));
writer.write("&client_secret=");
writer.write("[MY CLIENT SECRET]");
writer.flush();
writer.close();
int responseCode = connection.getResponseCode();
BufferedReader reader = new BufferedReader(new InputStreamReader(
        connection.getInputStream()));

我得到的响应代码是 401。在它尝试从连接中获取 inputStream 的最后一行中,它抛出了一个异常,这对我来说是有意义的,它返回了一个 401 并且没有。

是的,redirect_uri 已编码。 (我不认为初始重定向到登录会起作用。)

我的蜘蛛侠感觉告诉我,我忽略了一些对我来说应该很明显的东西,但我已经尝试了我能想到的一切。任何帮助将不胜感激。

编辑:更改了添加身份验证标头的方式,现在得到响应代码 400。

【问题讨论】:

  • 请记住 Authorization Basic 应该是 ":" 的 base64 编码,在这种情况下,用户将是 app id 和密码 app secret。

标签: java oauth oauth2


【解决方案1】:

您应该检查您是否正在创建正确的基本身份验证标头。应该是这样的:

String user = "your app id";
String password = "your app secret";
String authValue = user + ":" + password;

Base64.Encoder encoder = Base64.getEncoder();
Bytes[] btyes = authValue.getBytes(StandardCharsets.UTF_8);

String authValueEncoded = encoder.encodeToString(bytes);

connection.addRequestProperty("Authorization",
                    "Basic "+authValueEncoded);

用户和密码的这个值是特定于 Mendeley 的。见http://dev.mendeley.com/reference/topics/authorization_auth_code.html的第四步

关于错误 400,您可能需要检查 grant_type、code 或 redirect_uri。请记住,代码只能使用一次。 来自文档:

由于 grant_type、code 和 redirect_uri 导致 HTTP 错误请求响应,状态为 400 Bad Request 和 JSON 格式的错误代码和消息:

HTTP/1.1 400 错误请求内容类型:application/json 内容长度:82

{"error":"invalid_grant","error_description":"无效的访问代码"}

缺少值会生成带有 invalid_request 错误代码的响应。 无效值(包括以前使用的代码)生成响应 带有 invalid_grant 错误代码。指定的值不是 authorization_code(或 refresh_token)生成带有 unsupported_grant_type 错误代码。

因此,您可能希望查看响应正文以查看问题所在。

【讨论】:

  • 我试过了。现在我收到响应代码 400,所以我不确定我是否正在取得进展。
  • 另外,由于您有 auth 标头,您可能不需要正文中的客户端 ID 和密码。不确定这是否会破坏某些东西。
  • 它不会破坏任何东西,但@fbiagi 是对的,不要将 clientid 和 secret 添加到请求的正文中。您已经在他的身份验证标头中传递了它们
猜你喜欢
  • 2017-03-14
  • 2016-06-26
  • 2020-12-14
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 2018-08-07
  • 2018-09-07
相关资源
最近更新 更多