What's wrong with my authorization syntax? Getting 403 - ImgurAPI - javascript

I'm trying to get a response from the Imgur API but despite my best efforts I seem to be passing the Client ID improperly.
const key = `Client-ID ${process.env.REACT_APP_IMGURKEY}`;
fetch(url, {
method: "GET",
headers: new Headers({
Authorization: key
})
})
result of the fetch is 403: invalid Client ID, I've double checked and confirmed client ID is valid.

You need to retrieve an access token in order to be able to make requests to "Authed" requests in Imgur's api.
More details: https://apidocs.imgur.com/?version=latest#authorization-and-oauth
Basically you need to redirect the user of your app to this URL:
const YOUR_CLIENT_ID = process.env.REACT_APP_IMGURKEY;
const url = 'https://api.imgur.com/oauth2/authorize?client_id=' + YOUR_CLIENT_ID + ' &response_type=token'
Then the user will see an Imgur page, asking them to give permission to your app. After the user agreed to give permission, they are taken back to the URL you configured in your application preferences, and the access token will be in the URL:
https://example.org/#access_token=ACCESS_TOKEN&expires_in=315360000&token_type=bearer&refresh_token=___&account_username=___&account_id=____
Then you can make requests passing the access token like this:
fetch(url, {
method: "GET",
headers: new Headers({
Authorization: "Bearer " + ACCESS_TOKEN
})
})

Related

Destiny 2 API recieving an auth token from endpoint using POST

Couple things to keep in mind, I'm a fairly beginner computer science student with a couple big projects under my belt. I mostly have been working with java so web is kinda new but seems easy enough to get used to.
I'm trying to send a post request to an endpoint that will return a membership id that I need.
I've been trying to follow along with these two documentation/guides:
https://github.com/Bungie-net/api/wiki/OAuth-Documentation
https://lowlidev.com.au/destiny/authentication-2#/tab-popup
On a side note, I really feel like there aren't many "get started" guides out there for working with the Bungie API but maybe that's intentional to prevent people from doing stupid stuff with people's accounts.
Anyways, I have successfully done the first part which is authorizing my app (registered on the bungie developers site) with the user's account using my client ID provided by Bungie. This returns a code inside the url that is your authorization code with the user's account. I have a kind of janky way of pulling it from the url, so any ideas of how I can improve it would be most appreciated.
document.getElementById("authButton").addEventListener("click", function(event) {
location.href = "https://www.bungie.net/en/OAuth/Authorize?client_id={my-client-id}&response_type=code&state=" + makeState(32);
});
var authCode = undefined;
if (window.location.href.includes("code=")) {
removeAuthButton();
authCode = window.location.href;
console.log(authCode);
var codeLoc = authCode.indexOf("code=");
var codeEndLoc = authCode.indexOf("&", 15);
authCode = authCode.substring(codeLoc + 5, codeEndLoc);
console.log(authCode);
}
This code is just executed after pressing a simple authorization button in the webpage, and bungie handles the redirect back to my page for me when I register my app.
Now after this, the documentation shows a POST request I need to make with the following:
POST https://www.bungie.net/platform/app/oauth/token/ HTTP/1.1
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
To stay with the urlencoded format, I have tried this code using an answer I found:
https://stackoverflow.com/a/53189376/16910197
document.getElementById("linkButton").addEventListener("click", function(event) {
fetch('https://www.bungie.net/Platform/App/OAuth/token/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'client_id': "{my-client-id}",
'grant_type': "authorization_code",
'code': authCode
})
}).then(function(response) {
console.log(response);
return response.json();
});
});
This isn't working and I have modified it every way possible to try and get it to work to no avail. What am I missing?
Here is what I am getting back if needed:
Response { type: "cors", url: "https://www.bungie.net/Platform/App/OAuth/token/", redirected: false, status: 400, ok: false, statusText: "Bad Request", headers: Headers, body: ReadableStream, bodyUsed: false }
I'm a little new to stackoverflow and this is my first question, so let me know if I can format it any better.
You need to call toString on URLSearchParams and send the Authorization header. If you haven't already, you should switch your API key to use the "Confidential" OAuth Client Type
document.getElementById("linkButton").addEventListener("click", function(event) {
fetch('https://www.bungie.net/Platform/App/OAuth/token/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${window.btoa(`${bungie_client_id}:${bungie_client_secret}`)}`
},
body: new URLSearchParams({
'client_id': "{my-client-id}",
'grant_type': "authorization_code",
'code': authCode
}).toString()
}).then(function(response) {
console.log(response);
return response.json();
});
});
In case you didn't, check the network request in browser dev tools to see what JavaScript is actually POSTing to the endpoint.
From a fellow Destiny API dev, please capitalise "token" in the endpoint path before I lose my mind!

API call (fetch) with user token through Javascript (React.js)

how are you guys doing??
I'm trying to fetch data (in React with JS) from a website X (that has cors-enabled) but need first to get a user token from a website Y and I don't know how to figure that out. Somehow I think that I have to get the user token from Y, save it in a variable and add it as a header on the other call but I'm kinda lost with the GET/POST methods.
By now what I have is this but somehow doesn't work, I think I'm not sending properly the head or making the actual calls correctly:
getToken(){
const url = 'websiteOfTheToken';
const response = await fetch(url);
const data = await response.json();
this.setState({
userToken: data.image
});
}
And:
getData(){
const response = await fetch('websiteOfTheData', {
method: 'POST',
mode: 'no-cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'accept': 'application/json',
'Content-Type': 'application/json'
},
redirect: 'follow',
referrerPolicy: 'no-referrer',
body: JSON.stringify({
title: '' // I don't know what is this doing
})
}).catch( error => {
console.log('Error fetching and parsing data ', error)
});
this.setState({
data: response.json()
});
}
Thank you in advance!!
A few things I want to say / ask about:
Typically you get the token after a successfull login, so a standard request for a token would be a post request with the user data.
An await in javascript works only inside async functions, read about it.
The most common practice for handling api responses (Promise) is to use then-catch blocks, read about it.
A typical JWT header you need to attach to your requests looks like this: "Authorization": "Bearer theactualtoken1234".
The body of the fetch post request is the actual data you're sending to the server. So its contents are totally arbitrary - I also don't have an idea what this "title": "" is doing...

How to use Client ID and Client Secret to fetch API in Javascript?

I am trying to make an api call in Javascript. I am fetching a URL and passing in options, as shown in the image. I am unable to access the API, because I believe I am not passing in my client ID and client secret properly. I also have a redirect URI, but I am unsure of how to specify these in my options and what the syntax is.
Does anyone have any advice on how I can specify this information? Also, is using btoa to convert it to base64 incorrect?
My options I am passing in to my fetch request:
const options = {
method: 'GET',
json: true,
agent: agent,
headers: {
Authorization: 'Basic ' + btoa(client_id + ':' + client_secret),
redirect_uri: `{URI HERE}
}
}
My options I am passing in to my fetch request
Thank you

How do I fetch cookie data with React?

I have a MERN + Passport.js application that is using fetch to make a call to my express API in order to retrieve data stored in a cookie. I have my React frontend routed to localhost:3000, and my backend routed to localhost:3001. My cookies are not being saved, and thus my session is not persisting within my browser. It is not an issue with the express-sessions or passport middleware, as when I use POSTMAN to execute the necessary calls to my API, the cookie is stored and the session persists.
It is only when I attempt to pass this information through/to my front end that things go wrong. I have been stumped for a while and can't seem to find an answer anywhere.
This is the line that I am using to save the cookie:
handleLogin(event) {
event.preventDefault();
fetch("http://localhost:3001/users/login", {
// credentials: 'include',
credentials: 'same-origin',
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password
})
})
// .then( (response) => response.json())
.then( (response )=> {
if(response.message){
alert(response.message);
}
})
Which correctly calls my API, which logs the current session, user data, and cookie.
Upon refreshing and making another request, I lose the cookie (it was never properly stored in the first place I think), and all session data.
This is the get request that I make whenever I navigate to a new page:
componentDidMount(){
var current_user = "";
fetch("http://localhost:3001/users/", {
// credentials: 'include',
credentials: 'same-origin',
method: "get",
headers: {
'Accept':'application/json',
'Content-Type': 'application/json'
}
})
// .then( (response)=> response.json())
.then( (response)=> {
if(response.user){
current_user = response.user;
this.setState({
user: current_user
}), ()=> console.log(response);
}
})
}
In response, I get an undefined user and no other response, and the cookie is never stored in my browser. But again, if I do this in POSTMAN, strictly doing the POST request followed by that GET request, the proper user data is returned and the cookie is shown in POSTMAN as well.
Any idea as to why fetch is not passing the cookie information back to my front end? I have tried both credentials: 'include' and credentials: same-origin.
Thank you!
It seems like the problem, or at least part of it, is your use of same-origin. From Mozilla docs (italics my own):
omit: Never send cookies.
same-origin: Send user credentials (cookies, basic http auth, etc..) if the URL is on the same origin as the calling script. This is the default value.
include: Always send user credentials (cookies, basic http auth, etc..), even for cross-origin calls.
The definition of "same origin" does not include different ports.
If you change same-origin to include, fetch should start managing your cookies correctly.
If not - do you know for sure that the cookie is "never stored in the browser"? With Chrome, you can check chrome://settings/siteData.

How to pass api ID and api Key as authentication parameters of HTTP request

I am having trouble acessing the Oxford Dictionary API. I keep getting the error 'Authentication parameters missing'.
I believe I am not properly passing the api ID and key.
I have referred to this documentation:
https://developer.oxforddictionaries.com/documentation/making-requests-to-the-api
https://developer.oxforddictionaries.com/documentation
Here is my code; trust me that the app id and key are the correct strings.
const url = 'https://od-api.oxforddictionaries.com/api/v1/entries/en/swim';
fetch(url, {
method: 'GET',
headers: new Headers({
'app_id': oxford.appId, 'app_key': oxford.appKey
}),
}).then(function(response) {
console.log(response);
});
If the site looking for Authentication header it may refer to Basic Auth Header, read more here. If that is true, you simply can append your header parameter with this:
var headers = new Headers()
headers.append('Authorization', 'Basic ' + base64.encode(app_id + ":" + app_key));
You may try with or without the encoding.
You may also try this if that does not work
const url = 'https://od-api.oxforddictionaries.com/api/v1/entries/en/swim';
fetch(url, {
method: 'GET',
headers: { //HERE IS THE DIFFERENCE
'app_id': oxford.appId, 'app_key': oxford.appKey
},
mode: 'no-cors'
}).then(function(response) {
console.log(response);
});
If that does not work,
another way to think of, it may be a CORS issue, you can read it more here
May this helps.
I found an answer to my question here. Looks like the API does not support client side application requests. Guess I'll have to create a server.

Categories