我正在用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
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;
}
}
答案 0 :(得分:2)
授予类型“密码”要求在POST参数(username
和password
)而不是Authorization: basic
标头中传递用户(或:资源所有者)的凭证。 / p>