I used ruby on rails to make RESTful api and also used doorkeeper to handle authentication and authorization. As you know the doorkeeper generate some OAuth2 api's and the two of the them that i need to use is /users which is the post request and /oauth/token that make token for me. The api that i make which are post, get, put works greate in postman and android studio and web browser. But the post api /users and /oauth/token which generated by the doorkeeper doesn't work in web browser but works great on android studio and postman. That was confused for me. The error that i take while calling this api is 404, I checked the ruby production log on the server and it says no route match. The string thing here is that the type of method and routes is correct.
This is the code that i used in the reactjs. i used axios:
var url="http://x.x.x.x/oauth/token";
axios.post(url,{
"username":"1",
"password":"password",
"grant_type":"password"
},{headers:{"Content-Type":"application/json"}}).then( (response) => {
console.log(response.data);
})
.catch( (error) => {
console.log(JSON.stringify(error));
});
And also used raw jQuery to make request and get the same error. all my api works well execpt this two api:
var firstname = document.forms["registerForm"]["first_name"].value;
var lastname = document.forms["registerForm"]["last_name"].value;
var pass = document.forms["registerForm"]["password"].value;
var passconfirm = document.forms["registerForm"]["password_confirmation"].value;
var json_data = {
"async": true,
"crossDomain": true,
"url": send,
"method": "POST",
"headers": {
"content-type": "application/json",
},
"processData": false,
"data":
{
"user": {
"user_name": username,
"password": pass,
"password_confirmation": passconfirm,
"user_type": "admin"
},
"profile": {
"first_name": firstname,
"last_name": lastname
}
}
}
$.ajax(json_data).done(function (response) {
console.log(response);
});
console.log(json_data['data']);
console.log(username);
the output of this code console.log(JSON.stringify(error)); is this:
{"config":{"transformRequest":{},"transformResponse":{},"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json;charset=utf-8"},"method":"post","url":"http://x.x.x.x/oauth/token.json","data":"{\"username\":\"1\",\"password\":\"password\",\"grant_type\":\"password\"}"},"request":{}}
I find the request header and response header into the browser:
Response Header:
Content-Type
application/json; charset=UTF-8
Content-Length
34
Connection
keep-alive
Status
404 Not Found
X-Request-Id
d593b73f-eec8-41cd-95cd-e4459663358c
X-Runtime
0.002108
Date
Mon, 13 Nov 2017 11:19:26 GMT
X-Powered-By
Phusion Passenger 5.1.11
Server
nginx/1.12.1 + Phusion Passenger 5.1.11
Request headers (427 B)
Host
x.x.x.x
User-Agent
Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/56.0
Accept
text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Language
en-US,en;q=0.5
Accept-Encoding
gzip, deflate
Access-Control-Request-Method
POST
Access-Control-Request-Headers
Origin
http://localhost:3000
Connection
keep-alive
I used ruby on rails to make RESTful api and also used doorkeeper to handle authentication and authorization. As you know the doorkeeper generate some OAuth2 api's and the two of the them that i need to use is /users which is the post request and /oauth/token that make token for me. The api that i make which are post, get, put works greate in postman and android studio and web browser. But the post api /users and /oauth/token which generated by the doorkeeper doesn't work in web browser but works great on android studio and postman. That was confused for me. The error that i take while calling this api is 404, I checked the ruby production log on the server and it says no route match. The string thing here is that the type of method and routes is correct.
This is the code that i used in the reactjs. i used axios:
var url="http://x.x.x.x/oauth/token";
axios.post(url,{
"username":"1",
"password":"password",
"grant_type":"password"
},{headers:{"Content-Type":"application/json"}}).then( (response) => {
console.log(response.data);
})
.catch( (error) => {
console.log(JSON.stringify(error));
});
And also used raw jQuery to make request and get the same error. all my api works well execpt this two api:
var firstname = document.forms["registerForm"]["first_name"].value;
var lastname = document.forms["registerForm"]["last_name"].value;
var pass = document.forms["registerForm"]["password"].value;
var passconfirm = document.forms["registerForm"]["password_confirmation"].value;
var json_data = {
"async": true,
"crossDomain": true,
"url": send,
"method": "POST",
"headers": {
"content-type": "application/json",
},
"processData": false,
"data":
{
"user": {
"user_name": username,
"password": pass,
"password_confirmation": passconfirm,
"user_type": "admin"
},
"profile": {
"first_name": firstname,
"last_name": lastname
}
}
}
$.ajax(json_data).done(function (response) {
console.log(response);
});
console.log(json_data['data']);
console.log(username);
the output of this code console.log(JSON.stringify(error)); is this:
{"config":{"transformRequest":{},"transformResponse":{},"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json;charset=utf-8"},"method":"post","url":"http://x.x.x.x/oauth/token.json","data":"{\"username\":\"1\",\"password\":\"password\",\"grant_type\":\"password\"}"},"request":{}}
I find the request header and response header into the browser:
Response Header:
Content-Type
application/json; charset=UTF-8
Content-Length
34
Connection
keep-alive
Status
404 Not Found
X-Request-Id
d593b73f-eec8-41cd-95cd-e4459663358c
X-Runtime
0.002108
Date
Mon, 13 Nov 2017 11:19:26 GMT
X-Powered-By
Phusion Passenger 5.1.11
Server
nginx/1.12.1 + Phusion Passenger 5.1.11
Request headers (427 B)
Host
x.x.x.x
User-Agent
Mozilla/5.0 (X11; Ubuntu; Linu…) Gecko/20100101 Firefox/56.0
Accept
text/html,application/xhtml+xm…plication/xml;q=0.9,*/*;q=0.8
Accept-Language
en-US,en;q=0.5
Accept-Encoding
gzip, deflate
Access-Control-Request-Method
POST
Access-Control-Request-Headers
Origin
http://localhost:3000
Connection
keep-alive
Share
Improve this question
edited Nov 25, 2017 at 6:23
Hussein Ojaghi
asked Nov 11, 2017 at 7:14
Hussein OjaghiHussein Ojaghi
2,3003 gold badges23 silver badges42 bronze badges
3
- Can you share the error message? – aks Commented Nov 11, 2017 at 13:02
-
This could be related to CORS, can you try using var
url="http://x.x.x.x/oauth/token.json"
? – aks Commented Nov 11, 2017 at 13:03 - yes i just added json to end of my endpoint but it doesn't worked and also did this tutorial about CORS like this enable-cors/server_nginx.html and added to my code – Hussein Ojaghi Commented Nov 11, 2017 at 13:29
4 Answers
Reset to default 2After checking their docs, it looks like you need to change Content-Type
header to application/x-www-form-urlencoded
and data as key=value
pair:
const data = 'username=1&password=password&grant_type=password'
or simply:
const formData = {
username: '1',
password: 'password',
grant_type: 'password',
}
const data = Object.keys(formData)
.map(prop => `${prop}=${formData[prop]}`)
.join('&')
Final result would be:
var url="http://x.x.x.x/oauth/token";
axios.post(url, data, {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
}).then( (response) => {
console.log(response.data);
})
.catch( (error) => {
console.log(JSON.stringify(error));
});
It seems it is because of CORS policy. You can rack-cores. It is a rack middleware and you will be able to make cross domain requests to your doorkeeper protected application
You need to configure in your OAuth settings to allow access to client web app. Check logs or error message which you get in api response.
function login(username, password, returnUrl) {
const formData = {
grant_type:"password",
client_id:"xxxxxxxx",
client_secret: "xxxxxxxxx",
redirect_uri:"xxxxxxxx./api/v1/accounts/profile/",
username:username,
password:password
}
const d = Object.keys(formData)
.map(prop => `${prop}=${formData[prop]}`)
.join('&')
const requestOptions = {
method: 'POST',
headers: {
"Content-Type": "application/x-www-form-urlencoded",
'Accept': 'application/json'
},
body: d
};
return fetch('xxx./o/token/', requestOptions)
.then(handlePostResponse)
.then(token => {
// login successful if there's a user in the response
if (token) {
token.token = token
}
console.log(token)
return token;
});
}