+ Start a Discussion
BenedictBenedict 

How to get access_token of REST API in Java?

Hi, I am trying to get the access token in Java and following the instructions on http://www.salesforce.com/us/developer/docs/chatterapi/index.htm
But I continuously get this error:

{"error":"unsupported_grant_type","error_description":"grant type not supported"}

 

My codes are here:

 

 

package admin;

 

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

 

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

 

import com.google.gson.Gson;

 

public class REST
{
String authURL = "https://login.salesforce.com/services/oauth2/authorize";
String tokenURL = "https://na14.salesforce.com/services/oauth2/token";
public static void main(String[] args) throws ClientProtocolException, IOException
{
REST rest = new REST();
}

public REST() throws ClientProtocolException, IOException
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost post = new HttpPost(tokenURL);
post.getParams().setParameter("client_id", "3MVG9rFJvQRVOvk6sl7xMXtrbyQb2XUv2vprLKWv0uxBLKFzNqtHJG6cmzuemPYDB3hPwqXsBlw0BGQPkb81P");
post.getParams().setParameter("client_secret", "4864720658246552438");
post.getParams().setParameter("grant_type", "password");
post.getParams().setParameter("username", "XXXX");
post.getParams().setParameter("password", "XXXX");
post.getParams().setParameter("redirect_uri", "https://login.salesforce.com/services/oauth2/success");
HttpResponse response = httpclient.execute(post);
JSONObject json = (JSONObject) JSONValue.parse(new InputStreamReader (response.getEntity().getContent()));
System.out.println(json);
}
}

 

Best Answer chosen by Admin (Salesforce Developers) 
willywuwillywu

For what it's worth, I got this code to work on my end (after realizing the new version of apache's HttpPost doesn't have a setParameter method):

 

    public REST() throws ClientProtocolException, IOException {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost post = new HttpPost(tokenURL);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("client_id", "3MVG9rFJvQRVOvk6sl7xMXtrbyQb2XUv2vprLKWv0uxBLKFzNqtHJG6cmzuemPYDB3hPwqXsBlw0BGQPkb81P"));
        params.add(new BasicNameValuePair("client_secret", "4864720658246552438"));
        params.add(new BasicNameValuePair("grant_type", "password"));
        params.add(new BasicNameValuePair("username", "XXXX"));
        params.add(new BasicNameValuePair("password", "XXXX"));
        post.setEntity(new UrlEncodedFormEntity(params));
        HttpResponse response = httpclient.execute(post);
        String body = EntityUtils.toString(response.getEntity());
        System.out.println(body);
    }

All Answers

ChrisOctagonChrisOctagon

Hi Benedict,

 

There is some more in-depth information on using OAuth, including the "password" grant_type, here: http://wiki.developerforce.com/page/Digging_Deeper_into_OAuth_2.0_at_Salesforce.com

 

I would strongly suggest that you avoid using the "password" grant type in most cases as it is the least secure option. The web server flow is best for web servers, and the user agent is best for mobile apps.

 

- Chris

BenedictBenedict

Hi Chris,

 

Thanks for providing the link. It is a good article about OAuth. But my problem is actually different. I am acting as the administrator and want to get user data from a java application, so I want to get the access token directly in my program instead of going to the login page.

 

I am a bit new to http programming in java, and don't really know how to do it. The password grant_type looks like the right solution, but it seems to be not supported, as shown above.

 

Do you know how to login as administrator and then start grabbing data using REST, purely in Java? 

VishalAscVishalAsc

I think you won't get access token this way, because access token is part of URL that redirects client to the "redirect_url".

BenedictBenedict

Hi Chris,

 

Indeed, as you said, the user-password flow of OAuth is not so safe for the users.

The documentation says it is supported though https://na14.salesforce.com/help/doc/en/remoteaccess_oauth_username_password_flow.htm. But right now it seems that this flow is completely shutdown, which I think is the reason why I get this error : {"error":"unsupported_grant_type","error_description":"grant type not supported"}

 

Since I am bulding a datamining algortihm to analyze user interactions, I really need to find out how to access the "@" (mention) data from inside a Java application. It seems that I cannot do this from the Webservices, since there is no SOQL query support that. The only option is REST, but it seems that I cannot get the access token without involving some brower and user clicks. What can I do in order to get the mention data from inside a Java program with the admin permission in Chatter?

ChrisOctagonChrisOctagon

Hi Benedict,

 

If you're running a Java application as an administrator from inside your company and not distributing the application, I guess the username/password flow makes sense. I am pretty sure that this flow is still supported by Salesforce. Can you post the exact HTTP request that you're making?

 

- Chris

ChrisOctagonChrisOctagon

oh, duh, sorry, you already posted the request :)

 

the doc for that flow is funny, in one place it says the grant_type is "password" and in the example it says "basic-credentials". could you try that instead?

ChrisOctagonChrisOctagon

and don't send "redirect_uri"

BenedictBenedict

Hi Chris,

 

I've tried both grant_type (password and basic-credentials), but neither worked. Also commenting out the redirecting_url does not change the result. I still think the user-password flow is somehow not working at salesforce side.

ChrisOctagonChrisOctagon

I think you should be making your requests to the authURL not the tokenURL.

 

That is, https://login.salesforce.com/services/oauth2/authorize

BenedictBenedict

Hmmm, this is what i get in response if i post the request to the authorization server:

HTTP/1.1 400 Bad Request [Server: , Content-Length: 83, Date: Fri, 16 Mar 2012 19:14:10 GMT]

ChrisOctagonChrisOctagon

Doh :( which exact URL are you posting to now, and which parameters are you providing?

ChrisOctagonChrisOctagon

I stand corrected, it looks like it actually is the token URL you use. There is a sample cURL request at this Stackoverflow question which shows how to do it:

 

http://stackoverflow.com/questions/4958453/oauth-2-0-to-salesforce-without-a-webpage

BenedictBenedict

Hi, Chris, it's quite annoying... thanks for attention. Here is a sum up of what happens:

 

The authorization URL

String authURL = "https://login.salesforce.com/services/oauth2/authorize";

 

The token URL
String tokenURL = "https://na14.salesforce.com/services/oauth2/token";

 

The post body:

HttpPost post = new HttpPost(tokenURL);
post.getParams().setParameter("client_id", "3MVG9rFJvQRVOvk6sl7xMXtrbyQb2XUv2vprLKWv0uxBLKFzNqtHJG6cmzuemPYDB3hPwqXsBlw0BGQPkb81P");
post.getParams().setParameter("client_secret", "4864720658246552438");
post.getParams().setParameter("grant_type", "password");
post.getParams().setParameter("username", "XXXX");
post.getParams().setParameter("password", "XXXX");
post.getParams().setParameter("redirect_uri", "https://login.salesforce.com/services/oauth2/success");

 

Response from tokenURL:

{"error":"unsupported_grant_type","error_description":"grant type not supported"}

 

Response from authURL:

HTTP/1.1 400 Bad Request [Server: , Content-Length: 83, Date: Fri, 16 Mar 2012 19:14:10 GMT]

 

 

BenedictBenedict

yeah, i think it aught to be the token server. I'm almost losing hope to do it from REST now...

ChrisOctagonChrisOctagon
SuperfellSuperfell

You probably need to a call to set the content-type header in your request. (with the value  application/x-www-form-urlencoded)

willywuwillywu

I haven't used this version of Apache's http client, but try adding your parameters like

post.setParameter("client_id", "...");

instead of

post.getParams().setParameter("client_id", "...");

 

It looks like getParams() returns an immutable copy of HttpPost's parameters, so the next call to setParameter doesn't operate on the post method's original set of parameters.

willywuwillywu

For what it's worth, I got this code to work on my end (after realizing the new version of apache's HttpPost doesn't have a setParameter method):

 

    public REST() throws ClientProtocolException, IOException {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost post = new HttpPost(tokenURL);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("client_id", "3MVG9rFJvQRVOvk6sl7xMXtrbyQb2XUv2vprLKWv0uxBLKFzNqtHJG6cmzuemPYDB3hPwqXsBlw0BGQPkb81P"));
        params.add(new BasicNameValuePair("client_secret", "4864720658246552438"));
        params.add(new BasicNameValuePair("grant_type", "password"));
        params.add(new BasicNameValuePair("username", "XXXX"));
        params.add(new BasicNameValuePair("password", "XXXX"));
        post.setEntity(new UrlEncodedFormEntity(params));
        HttpResponse response = httpclient.execute(post);
        String body = EntityUtils.toString(response.getEntity());
        System.out.println(body);
    }

This was selected as the best answer
BenedictBenedict

Thanks! Willy! It worked! Amazing!

Thanks Chris, for bringing in the expert.

Thanks Simon, too!

VishalAscVishalAsc

By any change you did you get this error "Response Code is missing from the response" while trying out this code?

khaled moezkhaled moez
HttpClient httpclient = new DefaultHttpClient();
        HttpPost post = new HttpPost(tokenURL);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("client_id", "3MVG9WtWSKUDG.x6DQBu52ihfH45a4HTytogCy7IRsQEtq3StudboNgdBn_SRk5279xzXHMNvHNoVXmzE7qBl"));
        params.add(new BasicNameValuePair("client_secret", "4950633791639976158"));
        params.add(new BasicNameValuePair("grant_type", "password"));
        params.add(new BasicNameValuePair("username", "xxxxx"));
        params.add(new BasicNameValuePair("password", "xxxxx"));
        post.setEntity(new UrlEncodedFormEntity(params));
        HttpResponse response = httpclient.execute(post);
        String body = EntityUtils.toString(response.getEntity());
        System.out.println(body);


i have this error plzzz help me


{"error_description":"authentication failure - Failed: API security token required","error":"invalid_grant"}
mannsandeepmannsandeep
Willywu, Benedict, 
I am trying same thing and tried almost all options. copying my code below. 

public class RestWork
{
    private static final String CONSUMER_KEY = "3MVG9PbXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXzCH";
    private static final String CONSUMER_SECRET = "11111111111111111111";
    private static final String URL = "https://cs21.salesforce.com/services/oauth2/token";
   
    public static void main(String[] args) throws IOException
    {
              HttpClient client =  new DefaultHttpClient();;
              String loginURL = "https://cs51.salesforce.com/services/oauth2/token";    
        
        HttpPost httpPost = new HttpPost(loginURL);
       
     params.add(new BasicNameValuePair("client_id",  URLEncoder.encode(CONSUMER_KEY,"UTF-8")));
     params.add(new BasicNameValuePair("client_secret",  URLEncoder.encode(CONSUMER_SECRET,"UTF-8")));
     params.add(new BasicNameValuePair("grant_type", URLEncoder.encode("password","UTF-8")));
     params.add(new BasicNameValuePair("username", "nmalik@provenir.com"));
     params.add(new BasicNameValuePair("password",  "Password123K4QfddqECLkon95ospp08uG6l"));
  
        httpPost.setEntity(new UrlEncodedFormEntity(params));
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
        HttpResponse response = client.execute(httpPost);
       String body = EntityUtils.toString(response.getEntity());
         System.out.println(body);
       
}
}



It is throwing Internal server error everytime. Can you please guide me through this, am i suppose to make some settings in salesforce?

Thanks,