Oauth2令牌调用失败,显示“请求缺少必填参数”。

huangapple go评论91阅读模式
英文:

Oauth2 token call failing with "request is missing a required parameter"

问题

private String tokenEndpoint = "https://xxxxxxxxxxxxx/oauth2/token";
private String client_id = "2xxxxxxxxxxxxxxxxx";
private String client_secret = "xxxxxxxxxxxxxxxxxxxx";
private String grant_type = "client_credentials";
private String scope = "projects:read";
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
        .loadTrustMaterial(null, acceptingTrustStrategy)
        .build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
        .setSSLSocketFactory(csf)
        .build();
HttpPost httpPost = new HttpPost(tokenEndpoint);
String base64Credentials = Base64.getEncoder().encodeToString((client_id + ":" + client_secret).getBytes());
httpPost.addHeader("Authorization","Bearer " +  base64Credentials);
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
StringEntity input = null;
try {
    input = new StringEntity("grant_type=" + grant_type + "&scope=" + scope);
    httpPost.setEntity(input);
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
String result = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
OAuthClient oauthClient = new OAuthClient();
String res = oauthClient.callService();
System.out.println(res);
英文:

I'm trying to connect to the REST API using application/x-www-form-urlencoded,
using the following parameters:

 private String tokenEndpoint = "https://xxxxxxxxxxxxx/oauth2/token";
	private String client_id = "2xxxxxxxxxxxxxxxxx";
	private String client_secret = "xxxxxxxxxxxxxxxxxxxx";
	private String grant_type = "client_credentials";
	private String scope = "projects:read";


and finally get the following error:

>{"error":"invalid_request","error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Client credentials missing or malformed in both HTTP Authorization header and HTTP POST body."}

My code is:

package testRestAPI;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import javax.net.ssl.SSLContext;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.TrustStrategy;


public class OAuthClient {

	private String tokenEndpoint = "https://xxxxxxxxxxxxx/oauth2/token";
	private String client_id = "2xxxxxxxxxxxxxxxxx";
	private String client_secret = "xxxxxxxxxxxxxxxxxxxx";
	private String grant_type = "client_credentials";
	private String scope = "projects:read";
	

	public String callService()  {


		String result = null;

		try {

                        //My site is set as insecure, so I set the following setting
			TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

			SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
					.loadTrustMaterial(null, acceptingTrustStrategy)
					.build();

			SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

			CloseableHttpClient httpClient = HttpClients.custom()
					.setSSLSocketFactory(csf)
					.build();


			/* HTTPCLIENT AND HTTPPOST OOBJECT */
			//		HttpClient httpClient = HttpClientBuilder.create().build();
			HttpPost httpPost = new HttpPost(tokenEndpoint);

			/* AUTHENTICATION CREDENTIALS ENCODING */
			String base64Credentials = Base64.getEncoder().encodeToString((client_id + ":" 
					+ client_secret).getBytes());

			/* HEADER INFO */
			httpPost.addHeader("Authorization","Bearer " +  base64Credentials);
			httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");

			//		/* PROXY CONFIG */
			//				HttpHost target = new HttpHost("proxy", 8080, "http");
			//				RequestConfig config = RequestConfig.custom().setProxy(target).build();
			//				httpPost.setConfig(config);

			/* OAUTH PARAMETERS ADDED TO BODY */
			StringEntity input = null;
			try {
				input = new StringEntity("grant_type=" + grant_type + "&scope=" + scope);
				httpPost.setEntity(input);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}

			/* SEND AND RETRIEVE RESPONSE */
			HttpResponse response = null;
			try {
				response = httpClient.execute(httpPost);
			} catch (IOException e) {
				e.printStackTrace();
			}

			/* RESPONSE AS STRING */
			//		String result = null;
			try {
				result = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		catch (Exception e) {
			// TODO: handle exception
		}
		return result;
	}

	public static void main(String[] args) {
		OAuthClient oauthClient = new OAuthClient();
		String res = oauthClient.callService();
		System.out.println(res);
	}
}

and finally get the following error:

> {"error":"invalid_request","error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Client credentials missing or malformed in both HTTP Authorization header and HTTP POST body."}

In Postman the connection is made successfully.Connection with Postman

link to Oauth provider Api Doc

答案1

得分: 0

以下是翻译好的内容:

主要问题是您未在表单中包含client_id和client_secret。我注意到使用Fiddlr时,Postman会在提交的表单上发送所有这些字段。

改进代码的其他更改,但可能不需要修复的问题包括:

  • 删除无意义的Authorization Bearer标头。Postman不会发送,也没有意义发送该标头,直到接收到令牌为止。

  • 用标准的UrlEncodedFormEntity替换自制的表单模拟,并传递一个List<NameValuePair>。它会将"Content-Type", "application/x-www-form-urlencoded"标头添加到请求中。

请尝试以下代码:

import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.TrustStrategy;

public class OAuthClient {

    private String tokenEndpoint = "https://xxxxxxxxxxxxx/oauth2/token";
    private String client_id = "2xxxxxxxxxxxxxxxxx";
    private String client_secret = "xxxxxxxxxxxxxxxxxxxx";
    private String grant_type = "client_credentials";
    private String scope = "projects:read";

    public String callService() {

        String result = null;

        try {

            // My site is set as insecure, so I set the following setting
            TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

            SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
                    .loadTrustMaterial(null, acceptingTrustStrategy)
                    .build();

            SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(csf)
                    .build();

            /* HTTPCLIENT AND HTTPPOST OOBJECT */
            HttpPost httpPost = new HttpPost(tokenEndpoint);

            /* OAUTH PARAMETERS ADDED TO FORM */
            List<NameValuePair> form = new ArrayList<>();
            form.add(new BasicNameValuePair("grant_type", grant_type));
            form.add(new BasicNameValuePair("scope", scope));
            form.add(new BasicNameValuePair("client_id", client_id)); // these two were missing
            form.add(new BasicNameValuePair("client_secret", client_secret));

            // UrlEncodedFormEntity is the standard way of building a form submission
            // and it removes the need to manually add the "Content-Type", "application/x-www-form-urlencoded" header
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, Consts.UTF_8);

            httpPost.setEntity(entity);

            /* SEND AND RETRIEVE RESPONSE */
            HttpResponse response = null;
            try {
                response = httpClient.execute(httpPost);
            } catch (IOException e) {
                e.printStackTrace();
            }

            /* RESPONSE AS STRING */
            // String result = null;
            try {
                result = IOUtils.toString(response.getEntity().getContent(), "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
        return result;
    }

    public static void main(String[] args) {
        OAuthClient oauthClient = new OAuthClient();
        String res = oauthClient.callService();
        System.out.println(res);
    }
}
英文:

There are a couple of issues with your code.

Primarily, you are not including the client_id and client_secret in the form. I observed with Fiddlr that Postman sends all these fields on a submitted form.

Other changes to improve, but probably not required to fix the code are to:

  • Remove the nonsense Authorization Bearer header. Postman does not
    send and doesn't make sense to send one until a token has been
    received.

  • Replaced the home-made form emulation and replaced with the standard
    UrlEncodedFormEntity passing a List&lt;NameValuePair&gt;. It adds the &quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot; header to the request.

Try this:

import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.SSLContext;
import org.apache.commons.io.IOUtils;
import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.TrustStrategy;
public class OAuthClient {
private String tokenEndpoint = &quot;https://xxxxxxxxxxxxx/oauth2/token&quot;;
private String client_id = &quot;2xxxxxxxxxxxxxxxxx&quot;;
private String client_secret = &quot;xxxxxxxxxxxxxxxxxxxx&quot;;
private String grant_type = &quot;client_credentials&quot;;
private String scope = &quot;projects:read&quot;;
public String callService()  {
String result = null;
try {
//My site is set as insecure, so I set the following setting
TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -&gt; true;
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(csf)
.build();
/* HTTPCLIENT AND HTTPPOST OOBJECT */
HttpPost httpPost = new HttpPost(tokenEndpoint);
/* OAUTH PARAMETERS ADDED TO FORM */
List&lt;NameValuePair&gt; form = new ArrayList&lt;&gt;();
form.add(new BasicNameValuePair(&quot;grant_type&quot;, grant_type));
form.add(new BasicNameValuePair(&quot;scope&quot;, scope));
form.add(new BasicNameValuePair(&quot;client_id&quot;, client_id)); // these two were missing
form.add(new BasicNameValuePair(&quot;client_secret&quot;, client_secret));
// UrlEncodedFormEntity is the standard way of building a firm submission
// and it removes the need to manually add the &quot;Content-Type&quot;, &quot;application/x-www-form-urlencoded&quot; header
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(form, Consts.UTF_8);
httpPost.setEntity(entity);
/* SEND AND RETRIEVE RESPONSE */
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
/* RESPONSE AS STRING */
//      String result = null;
try {
result = IOUtils.toString(response.getEntity().getContent(), &quot;UTF-8&quot;);
} catch (IOException e) {
e.printStackTrace();
}
}
catch (Exception e) {
// TODO: handle exception
}
return result;
}
public static void main(String[] args) {
OAuthClient oauthClient = new OAuthClient();
String res = oauthClient.callService();
System.out.println(res);
}
}

huangapple
  • 本文由 发表于 2023年4月19日 14:42:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76051445.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定