I come to you in a time of great need. I've spent like a week on this and still can't figure it out. Please help.
Here is what I want to do:
I've got a WordPress website (http://test/test.wp/) on which you can do the following API call right in the browser when you are logged in:
$.ajax({
url: 'http://test/test.wp/wp-json/wp/v2/users/me',
method: 'GET',
beforeSend: function(xhr){
xhr.setRequestHeader( 'X-WP-Nonce', wpApiSettings.nonce );
}
}).done(function(response){
console.log(response);
}).fail(function(response){
console.log( response.responseJSON.message );
});
And it works just fine. You get a Json about the current user (I just need the ID)
Now, I got another website (subdomain) written in React (http://app.test) and I am trying to pretty much do the same GET request to WordPress to grab the ID of the currently logged in User.
The sites are interconnected and I am sort of trying to imitate a SSO between WordPress and React by simply grabbing the ID of the currently logged in user in WordPress and using it in the react subdomain
To achieve this I've taken care of the CORS so I can make GET request from React to WordPress with no problems.
I also shared my WordPress wordpress_logged_in_cffb670352ad40cd796ad890d27ee701 cookie with the React subdomain so I've got access to that (which, from what I understand is the only cookie needed to keep you authenticated)
So, with all of that said why is my request from React failing?
Axios({
method: 'get',
url: 'http://test/test.wp/wp-json/wp/v2/users/me',
headers: {
'X-WP-Nonce': '659cbfeec0', // <= It's needed to use the WP Api and it's correct. I mannually grabed it from WP with wpApiSettings.nonce
withCredentials: true, // <= From what I understand is the only thing needed to send the `wordpress_logged_in_cffb670352ad40cd796ad890d27ee701` cookie ???
},
})
.then(response => console.log(response))
.catch(err => console.log(err));
So why then the answer that I get is a 403 (Forbidden)?:
code: "rest_cookie_invalid_nonce"
data: {status: 403}
statusText: 'Forbidden'
message: "Cookie verification failed"
You can say that the answer is in the response that I get, but I really have no idea why that's the case.
Please help.
Desperate Coder.
I was passing the 'with-Credentials' in the Headers and was not sending the cookies in the request because of that.
The correct way of doing it is:
Axios.get(
'http://test/test.wp/wp-json/wp/v2/users/me',
{
withCredentials: true,
headers: { 'X-WP-NONCE': 'Your_Nonce' },
}
)
Related
Im banging my head and cant solve the mystery :(.
I've rails app and react, rails app returns Authorization bearer token in response header and also it returns Access-Control-Expose-Headers: Authorization
I see in the responses that everything is returned properly, but when I try to get value of Authorization header using response.headers.get('Authorization') Im getting null
My Fetch looks like:
fetch('/users/sign_in.json', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'X-CSRF-Token': token},
body: JSON.stringify({ user: values })
})
.then((response) => console.log(response.headers.get('Authorization')))
.then((data) => console.log(data))
What Im missing?
Ive checked cookies - rails does not save token into cookie, Im using devise-jwt gem. Thanks for any hint.
Problem solved...
When user signs in, in first response he gets Authorization header. I've tried sign in already signed user, and I'didnt get any proper header although in chrome debugger Authorization header was present in response :/
I've been trying to develop with the new Forge Dataviz NPM packages for a while but I've been facing errors. I'm currently just trying to load a Viewer (https://forge.autodesk.com/en/docs/dataviz/v1/reference/UI/Viewer/) but I think I'm doing something wrong. Still don't know what.
This is my React const :
const TestAutodesk= () => {
return (
<div>
<Viewer
env="AutodeskProduction"
docUrn="URN STRING"
getToken={async () => await fetch("https://developer.api.autodesk.com/authentication/v1/authenticate",requestOptions)
.then((res) => res.json())
.then((data) => data.access_token)}
></Viewer>
</div>
);
};
These are the requestOptions:
myHeaders.append("Content-Type", "application/x-www-form-urlencoded");
var urlencoded = new URLSearchParams();
urlencoded.append("client_id", "ID");
urlencoded.append("client_secret", "SECRET");
urlencoded.append("grant_type", "client_credentials");
var requestOptions = {
method: "POST",
headers: myHeaders,
body: urlencoded,
redirect: "follow",
};
The final app is not going to use this as the auth, I'm going use a safe backend endpoint, this is just for trying to get the viewer loaded and the front end done. This is the error I get on the console:
I think the error is that is calling localhost:8080 but it should call an autodesk endpoint. Any idea on this? The Api reference / Dataviz example doesnt say anything about this.
The <Viewer> React component is pretty simple (https://github.com/Autodesk-Forge/forge-dataviz-iot-react-components/blob/main/client/components/Viewer.jsx), and shouldn't itself make any requests to localhost. Are you perhaps making those requests somewhere else in your application?
Regarding the getToken implementation, I'd suggest two things:
It's not a good practice to make these requests directly from the client-side code. This way, someone could potentially steal your Forge client ID and client secret. A better approach is to implement a custom endpoint in your own backend that generates the token with limited privileges, hiding the credentials from the client.
If you need to make the raw request to https://developer.api.autodesk.com/authentication/v1/authenticate, note that it requires 4 (not 3) parameters: client_id, client_secret, grant_type, and scopes.
I am trying to get some of the examples located in the with-ireon-sessions github account to work with my own back-end: https://github.com/vercel/next.js/tree/canary/examples/with-iron-session
I can sign in using const { user, mutateUser } = useUser(); with useUser() being from the example: https://github.com/vercel/next.js/blob/canary/examples/with-iron-session/lib/useUser.js
My sign-in method looks like this;
const signIn = async ({ email, password, remember_me }) => {
try {
await mutateUser(
fetchJson(`${API.baseURL}/${API.signIn}`, {
method: "POST",
headers: {
"Accept": 'application/json',
"Content-Type": "application/json"
},
body: JSON.stringify({
email,
password
})
})
);
} catch (error) {
console.error("An unexpected error happened:", error);
setErrorMessage((<p className="error">{error.data.message}</p>));
}
};
I can see my user change, but I still have the following issues:
I don't see any cookies get created. Does with-iron-sessions require the site to be deployed to the vercel cloud in order for cookies to get added, or am I right in thinking I can use my own server and API endpoints?
What's the pattern for using the /api/user endpoint in useUser.js; does the endpoint look for the cookies (that are not getting created for me) and do it's own validation, or is there validation I need to do in my version of that endpoint? Is there an example of what that endpoint looks like server-side you might be able to point me to?
Is there a way to refresh the cookie (once I get them to appear) so they are X days since last using the site instead of X days from first login so it's a sliding cookie lifespan, or does that happen automatically?
When I sign out my sign_out endpoint returns a 204 status code but the UI doesn't change like it does when I sign in. Any tips for me there?
Thank you!
I have a React app in which I use the HERE Geocoding API. I have an axios request to retrieve latitude and longitude and it does not work as well as expected. The request is not working inside my app
return axios.get(`https://geocode.search.hereapi.com/v1/geocode?q=${address}&apiKey=myAPIKey`)
I have a 401 error. Bearer token invalid. Bearer missing or bearer value missing. If I open a new tab in my browser and paste the url https://geocode.search.hereapi.com/v1/geocode?q=${address}&apiKey=myAPIKey it works fine and I get the result I need.
I tried using the Authorization header
const config = {
headers: {
'Accept': 'application/json',
'Authorization': `apiKey myAPIKey`,
}
};
return axios.get(`https://geocode.search.hereapi.com/v1/geocode?q=${address}&apiKey=myAPIKey`,config)
In the Authorization header, I tried with Bearer and Basic instead of apiKey
documentation HERE API
In the documentation about how to create an API Key and how to use it, the only thing I need to do is what I have already done. I have created a project, an API Key and I use it in my request.
HERE Geocoding API Key
I don't know how the HERE api works but the error message is probably the answer you are looking for.
You are likely to provide the api key via the Authorization header with your request. Read about the header on MDN
You just need to pass your API key in the link as a parameter.
Just sign up and you can get your API key.
https://developer.here.com/sign-up
The code should be like this.
return axios.get(`https://geocode.search.hereapi.com/v1/geocode?q=${address}&apiKey=${HERE_MAP_API_KEY}`,config)
The latest request would look like this.
axios.get(`https://geocoder.ls.hereapi.com/search/6.2/geocode.json?languages=en-US&maxresults=${maxResults}&searchtext=${query}&apiKey=${HERE_MAP_API_KEY}`)
.then(res => {
const data = res.data
console.log(data)
})
.catch(err => console.log(err))
I've been trying to make an React site, which would fetch a GET-response from API and print it out to my .html-file. I've managed to fetch the file just right, but i can't access the JSON-data server sends me.
If i use no-cors in my Fetch-request, i get an opaque response containing pretty much nothing, but if i go to Developer tools i can find my data there and read it. If i do use cors, almost same thing. I get an 403-error, but my data is in the browser memory, but my code doesn't print it out. I can find the response from Network in developer tools.
Why does the server give me an error, but still i get my data? And how can i access it, if it's in the browser?
class Clock extends React.Component {
constructor(props) {
super(props)
this.state = {data2: []}
this.apihaku = this.apihaku.bind(this)
}
componentDidMount() {
this.apihaku(),
console.log("Hei")
}
apihaku () {
fetch('https://#######/mapi/profile/',
{method: 'GET', mode:'no-cors', credentials: 'include',
headers: {Accept: 'application/json'}}
).then((response) => {
console.log(response);
response.json().then((data) =>{
console.log(data);
});
});
}
render() {
return <div>
<button>Button</button>
</div>
}}
ReactDOM.render(
<Clock />,
document.getElementById('content')
)
EDIT: Error images after trying out suggestions
https://i.stack.imgur.com/wp693.png
https://i.stack.imgur.com/07rSG.png
https://i.stack.imgur.com/XwZsR.png
You're getting an opaque response, because you're using fetch with mode: 'no-cors'. You need to use mode: 'cors' and the server needs to send the required CORS headers in order to access the response.
Fetch is doing exactly what the documentation says it's supposed to do, from Mozilla:
The fetch specification differs from jQuery.ajax() in two main ways:
The Promise returned from fetch() won’t reject on HTTP error status
even if the response is an HTTP 404 or 500. Instead, it will resolve
normally (with ok status set to false), and it will only reject on
network failure or if anything prevented the request from completing.
By default, fetch won't send or receive any cookies from the server,
resulting in unauthenticated requests if the site relies on
maintaining a user session (to send cookies, the credentials init
option must be set). Since Aug 25, 2017. The spec changed the default
credentials policy to same-origin. Firefox changed since 61.0b13.
So you need to use CORS, otherwise you get an opaque response (no JSON), and then 403 to me suggests that you haven't authenticated properly. Test your API with Postman, if I had to take a guess I'd say the API isn't sending the cookie because it's a GET request, so no matter how well you set your headers on the client it won't work. Try it as a POST instead. GET requests should really only be used to drop the initial HTML in the browser. I think for your headers use these, include the creds that the API sends and allow the domain to be different.
mode: "cors", // no-cors, cors, *same-origin *=default
credentials: "include", // *same-origin
Try this and see where is the error happening i believe in the parsing but lets check and see
fetch(https://#######/mapi/profile/, {
method: "GET",
headers: {
"Content-Type": "application/json"
},
credentials: "include"
})
.then((response) => {
console.log(response);
try {
JSON.parse(response)
}
catch(err){
console.log("parsing err ",err)
}
})
.catch((err)=>{
console.log("err ",err)
});
I had a similar issue, this kind of problem happend when a HTTP port try to send request to a HTTPS endpoint, adding a "mode:'no-cors'" doesn't do what is SOUND doing but rathere when the documentation says.
I fixed the issue by allowing in my API Application for calls from my HTTP port
(i'm using a .net 6 as an API in debugging mode, my code look like this https://stackoverflow.com/a/31942128/9570006)