获取OAuth2访问令牌失败,并显示错误消息“ HTTP / 1.1 401未经授权”

时间:2018-08-28 11:56:22

标签: oauth-2.0 access-token cas pingfederate

我正在用JAVA编写OAuth客户端,以从中央身份验证服务(PingFederate)获取OAuth令牌。由于此客户端是独立的实用程序,因此它后面没有应用程序服务器。

我正在尝试实现: 一个独立的JAVA客户端应从PingFederate获取OAuth令牌,例如,应允许一定范围。 TEST_READ。获得访问令牌后,我会将其传递给资源提供商。

因此,根据PingFederate文档,此类独立客户端应使用Grant Type =资源所有者密码凭据,并获取Oauth令牌POST请求应包含用户名/密码以及客户端ID和密码。

当我尝试相同的操作时,收到错误消息:

HTTP/1.1 401 Unauthorized [Date: Tue, 28 Aug 2018 09:04:50 GMT, Content-Security-Policy: referrer origin, X-Frame-Options: SAMEORIGIN, Cache-Control: no-cache, no-store, Pragma: no-cache, Expires: Thu, 01 Jan 1970 00:00:00 GMT, Content-Type: application/json;charset=utf-8, WWW-Authenticate: basic realm="PF AS Token Endpoints", Set-Cookie: PF=zVXrZpsAmWwrrVkzgltJZ4;Path=/;Secure;HttpOnly, Transfer-Encoding: chunked] org.apache.http.conn.BasicManagedEntity@68c9133c

要深入研究它,我检查了PingFederate audit.log,在其中找到了日志:AS| failure| | invalid_client: client_id value doesn't match HTTP Basic username value| 0

这是我的JAVA客户端代码

package com.auth;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.simple.parser.JSONParser;

public class OAuth2Client {

    public static final String GRANT_TYPE = "grant_type";
    public static final String CLIENT_ID = "client_id";
    public static final String CLIENT_SECRET = "client_secret";
    private static final String AUTHORIZATION = "Authorization";
    public static final String BASIC = "Basic";
    public static final String ACCESS_TOKEN = "access_token";
    public static final String SCOPE = "scope";

    public static void main(String[] args) {
        System.out.println(getAccessToken());
    }

    public static String getAccessToken() {
        HttpPost post = new HttpPost(
                "https://localhost:9031/as/token.oauth2");
        String clientId = "OAUTH-CLIENT-TEST";
        String clientSecret = "OAUTH-CLIENT-TEST-SECRET";
        String scope = "TEST_READ";
        String username = "testuser";
        String password = "test#001Pass";

        List<BasicNameValuePair> parametersBody = new ArrayList<BasicNameValuePair>();
        parametersBody.add(new BasicNameValuePair(GRANT_TYPE, "password"));

        parametersBody.add(new BasicNameValuePair(CLIENT_ID, clientId));
        parametersBody.add(new BasicNameValuePair(CLIENT_SECRET, clientSecret));
        parametersBody.add(new BasicNameValuePair(SCOPE, scope));

        DefaultHttpClient client = new DefaultHttpClient();
        HttpResponse response = null;
        String accessToken = null;
        try {
            //post.setEntity(new UrlEncodedFormEntity(parametersBody, HTTP.UTF_8));
            post.setEntity(new UrlEncodedFormEntity(parametersBody));

            post.addHeader(AUTHORIZATION,
                    BASIC + " " + encodeCredentials(username, password));
            post.addHeader("Content-Type", "application/x-www-form-urlencoded");

            response = client.execute(post);

            int code = response.getStatusLine().getStatusCode();

            if (code >= 400) {
                throw new RuntimeException(
                        "Could not retrieve access token for user: " + username);
            }
            Map<String, String> map = handleJsonResponse(response);
            accessToken = map.get(ACCESS_TOKEN);
        } catch (ClientProtocolException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        }

        return accessToken;
    }

    public static String encodeCredentials(String username, String password) {
        String cred = username + ":" + password;
        String encodedValue = null;
        byte[] encodedBytes = Base64.encodeBase64(cred.getBytes());
        encodedValue = new String(encodedBytes);
        System.out.println("encodedBytes " + new String(encodedBytes));

        byte[] decodedBytes = Base64.decodeBase64(encodedBytes);
        System.out.println("decodedBytes " + new String(decodedBytes));

        return encodedValue;

    }

    public static Map handleJsonResponse(HttpResponse response) {
        Map<String, String> responseMap = null;
        String contentType = response.getEntity().getContentType().getValue();
        try {
            responseMap = (Map<String, String>) new JSONParser()
                    .parse(EntityUtils.toString(response.getEntity()));
        } catch (ParseException e) {
            e.printStackTrace();
            throw new RuntimeException();
        } catch (org.json.simple.parser.ParseException e) {
            e.printStackTrace();
            throw new RuntimeException();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        } catch (RuntimeException e) {
            System.out.println("Could not parse JSON response");
            throw e;
        }
        System.out.println();
        System.out.println("********** Response Received **********");
        for (Map.Entry<String, String> entry : responseMap.entrySet()) {
            System.out.println(String.format("  %s = %s", entry.getKey(),
                    entry.getValue()));
        }
        return responseMap;
    }
}

1 个答案:

答案 0 :(得分:2)

授予类型“密码”要求在POST参数(usernamepassword)而不是Authorization: basic标头中传递用户(或:资源所有者)的凭证。 / p>