I know there's already a lot of discussion around the "unsupported_grant_type" error that occurs when using the Username/Password Authentication Flow, but I've exhausted through all other proposed solutions and am still having problems. I've found that from the Angular.JS app, I will get the error, but when I use cURL, it works fine.
The current route of the request originates on localhost:3001, goes through a proxy running on that same localhost at localhost:3001/proxy, where the request is then routed to the Salesforce instance. The proxy is made using Express.JS and the client side app is made using Angular.JS. Note: I did remember to tag my security token at the end of my password, although when using cURL, this doesn't seem to be necessary. Here are a series of HTTP traces that will hopefully provide some clues:
HTTP Request Log from Angular.JS App:
POST /proxy HTTP/1.1
Host: localhost:3001
Connection: keep-alive
Content-Length: 234
Pragma: no-cache
Cache-Control: no-cache
X-User-Agent: salesforce-toolkit-rest-javascript/v29.0
Origin: http://localhost:3001
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/plain, */*
SalesforceProxy-Endpoint: https://uniquename.salesforce.com/services/oauth2/token
Referer: http://localhost:3001/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: liveagent_oref=; liveagent_ptid=3c69c2f9-139d-4439-ba6c-fd8d9dcae101; liveagent_vc=5
grant_type=password&client_id=3MVGxyzxyzxyzxyz&client_secret=99889988&username=first.last%40email.com&password=pswdwACYodaYfHs
400 Bad Request
Object {error_description: "grant type not supported", error: "unsupported_grant_type"}
Relevant Express.JS code used for proxy routing:
app.all('/proxy', function(req, res) {
var url = req.header('SalesforceProxy-Endpoint');
console.log(req.body); //prints all form data variables in JSON format
console.log(res.body); //undefined
request({url: url}).pipe(res).on('error', function(error){
console.log(error);
});
});
Request details using cURL:
curl -v https://uniquename.salesforce.com/services/oauth2/token
-d "grant_type=password" -d "client_id=3MVGxyzxyzxyzxyz"
-d "client_secret=99889988" -d "username=jfirst.last@email.com" -d "password=pswd"
> POST /services/oauth2/token HTTP/1.1
> User-Agent: curl/7.41.0
> Host: uniquename.salesforce.com
> Accept: */*
> Content-Length: 207
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 207 out of 207 bytes
< HTTP/1.1 200 OK
< Date: Wed, 29 Jul 2015 06:04:55 GMT
< Set-Cookie: BrowserId=auu1mgvHSMS1EedDEduz8Q;Path=/;Domain=.salesforce.com;Exp
ires=Sun, 27-Sep-2015 06:04:55 GMT
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Pragma: no-cache
< Cache-Control: no-cache, no-store
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
<
{
"id":"https://test.salesforce.com/id/05390530530",
"issued_at":"1438132525896197",
"token_type":"Bearer",
"instance_url":"https://uniquename.salesforce.com",
"signature":"blahblah",
"access_token":"XXXXXXXXXXXXXXXXX"
}
* Connection #0 to
host uniquename.salesforce.com left intact
As you can see, I get back a valid response from the cURL request. I suspect something is wrong with the proxy, as it may not be forwarding all the form data to Salesforce, but I'm not sure how to debug that in Express.JS. The reason I suspect this is because if I try curl https://uniquename.salesforce.com/services/oauth2/token
it returns the same unsupported_grant_type
error.
UPDATE: I got past the original error by including an Accept: '*/*'
header in my request. Now I'm getting a response back from Salesforce saying:
HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, OPTIONS
Date: Tue, 04 Aug 2015 21:58:53 GMT
Connection: keep-alive
Transfer-Encoding: chunked
Does anyone know how to enable POST on my instance? Remember, I'm using the Username/Password auth flow.