Passing authorization to cloudinary in react - reactjs

I'm making the front of an app in react and i need to upload images to cloudinary passing the key and secret. I tried this:
function handleFiles(files) {
const url = CLOUDINARY_URL
const formData = new FormData()
formData.append("file",files[0])
formData.append('upload_preset',IMAGE_FOLDER)
fetch(url,{
method: "POST",
//headers: {
// 'Authorization': 'Basic ' + CLOUDINARY_KEY + ":" + CLOUDINARY_SECRET,
//},
body: formData
}).then(response => {console.log("resp ",response); return response.text()})
.then(data => console.log("data ", data))
}
This code works fine with a cloud name that doesn't need authorization but when i uncomment the header part give me the next error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at CLOUDINARY_URL. (Reason: header ‘authorization’ is not allowed according to header ‘Access-Control-Allow-Headers’ from CORS preflight response)
How can i achieve this? Or is there other way to upload images from react?
Thanks in advance.

Cloudinary Upload API does not use Basic Authorization method to signed your upload. However it can be uploaded using Signed Upload preset that signed with your backend or unsigned upload preset. I suggest to check their documentation to learn the difference.
The easiest to upload via web, although it's not specific to React, is to use Cloudinary's Upload Widget. This is JavaScript based solution that you can integrate with your React App
On a last note, just keep in mind that your API credential, specifically API Secret should be treated as if it's your password. Since React is a client-side application, you should not put your API secret there.

Related

Ensure that image was captured from the Camera in React

So I am building a face recognition based login system. I am using React on the Frontend and a Python based API for the backend.
I am using the "react-webcam" package to click a photo of the user and sending it to the backend endpoint to login. The code for this is
const face_uri = face.canvas.toDataURL("image/jpeg")
const request = new Request('/api/login',{
method: 'POST',
body: JSON.stringify({
face:face_uri
}),
headers: {
accept: 'application/json',
},
})
const response = await fetch(request);
I do face detecting and matching on the server side and return a JWT if a face is found and matched.
My problem is anyone could get a base64 encoded image of another person and post that to my endpoint '/api/login' and gain access to someone else's account.
How do I ensure that the image being sent to the backend was clicked right now from the camera?
Please let me know of any suggestions you have, even if it involves using a completely different approach, language, framework etc.

Firebase Auth: getIdToken on every fetch or set cookie?

I'm currently working on a Next.js (React) project, where I use Firebase Auth for authentication. I use this to connect to a REST API back-end, which receives the user token Firebase provides (via getIdToken()).
Because the IdToken changes every now and then, I'm currently reqesting the latest IdToken before sending a fetch request like this:
const fetcher = (url: string) => {
return user.getIdToken().then((token) =>
fetch(url, {
method: "GET",
headers: new Headers({
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
}),
}).then((res) => res.json())
);
};
This setup actually works, but I was wondering if it's considered efficient/best-practice?
I see a lot of examples out there where the IdToken is used to set a cookie (eg. firebase docs, next.js example).
I could see why when using SSR, since getIdToken() can't be called there. But my application only uses client-side data fetching. Would there be any benefits for me moving away from my current approach to using cookies?
The Firebase Authentication SDK already caches the token in local storage, so there's no need for you to cache it elsewhere again.
In fact, the token is refreshed every hour, and the Firebase Authentication SDK refreshes it automatically in the background. If you cache the token yourself, you might end up using an outdated token.
So I'd recommend always calling getIdToken() when you need the ID token. Of course it's fine to store it in a variable, and use that in a single code block (code that runs at pretty much the same time).
Using a cookie to pass the token to your server is fine, as is using the Authorization header as you do now. The latter is more common, but a cookie works too.

How to overwrite content type in react js fetch method while sending CSV

I'am sending content type as Text/csv as my API accept only the text/csv type but the file's content type is showing as application/vnd.ms-excel.
I've also checked with the postman, API is accepting the file in the http request but when I'am sending through my browser application it returns the response unsupported media type
How can I solve this.
Please go through the code:
var Authorization=window.sessionStorage.getItem('acesstToken')
var Headers={
'Authorization': 'Bearer '+Authorization,
'Content-Type': 'text/csv',
}
const fd = new FormData()
fd.append('csv_file',fieldValues.file[0],fieldValues.file[0].name);
var url="XXXXXXXXXXXXXXX";
fetch(url,{
method : 'POST',
headers: Headers,
body: fd,
})
Here's my bet.
Possible syntax issue. You're missing the closing quote for the 'Content-Type': 'text/csv'. Are you sure there aren't any syntax errors in your console?
If it works with Postman (it accepts the file), but it doesn't work through your browser application, my bet is that could be an issue is with the same-origin policy.
In the no-cors mode, the browser is limited to sending “simple” requests — those with safelisted methods and safelisted headers only. To send a cross-origin request with headers like Authorization, you have to drop the no-cors mode and support preflight requests (OPTIONS) for your API. See this answer.

Can't connect to API using React.js fetch method

I'm trying to connect to buffer's API (https://buffer.com/developers/api/oauth) via react.js using fetch(), but I'm getting a 400 error response.
This is running on my localhost but the site's accessible from the Internet.
Here's my code:
const queryString = require('query-string');
const parsed = queryString.parse(window.location.search);
const buffer_data = {
client_id: BUFFER_CLIENT_ID,
client_secret: BUFFER_CLIENT_SECRET,
redirect_uri: BUFFER_CALLBACK_URL,
code: parsed.code,
grant_type: 'authorization_code',
};
fetch(BUFFER_ACCESS_TOKEN_URL, {
method: 'post',
body: JSON.stringify(buffer_data),
}).then( data => {
console.log('data response ' + data);
return data.json();
}).then( response => {
console.log(response);
});
And here's the response:
{"error":"invalid_request","error_description":"Invalid grant_type
parameter or parameter missing"}
And the console prints this:
Failed to load https://api.bufferapp.com/1/oauth2/token.json: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://myserver.com' is therefore not allowed
access. The response had HTTP status code 400. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
I've tried lots of things, like not serializing the data, trying sending many different headers, using a CORS chrome plugin, etc
Before coding this in react, I've successfully connected using PHP, but to do that I had to add an SSL certificate on my server.
I'm also open to use any library but haven't found one to do this job. Or any other fetching method, like axios?
Many thanks!
I don't know which browser you are using, but you might want to add Allow-Control-Allow-Origin
for your chrome browser (if you are using chrome). This is some issue that seems to occur when you are using localhost with chrome.
Also, i highly recommend using axios for fetching API's, it comes with some easy error logs that can help you pinning down the issue pretty fast.
Greetings!

Bad Request (400) When Trying to Authenticate Harvest API in React

So I'm building a status board for our internal use as developers here in the office. It will show number of commits, hours tracked, etc.
I am following this model for authenticating. After a user logs in with harvest it redirects them back to the app with the code param as a query string, I'm then taking that query string and passing it to a state to then do a fetch to get the access token (so that I can later pull API data).
What happens, is the login is successful but when you are redirected back to the app the fetch throws a Bad Request (400) error. I have tested in Postman and can get the correct response so I'm not sure what the issue is...
Here is some of the JS from the Main component that sets the states if there is a code param:
harvestState() {
// grab URL params
let urlParams = queryString.parse(location.search);
console.log(urlParams);
console.log(urlParams.code);
// set the state based on the paramater passed back
urlParams.code ? (
this.setState({
harvestcode: urlParams.code
})
) : (
this.setState({
harvestcode: 'none'
})
);
}
componentWillMount(){
this.harvestState();
}
And here is the fetch function in my Harvest component:
getHarvest(){
const clientSecret = 'XXXXXXXXXX';
// Set Harvest Headers
const harvestHeaders = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
mode: 'no-cors',
body: {
'code': this.props.code,
'client_id': this.props.clientid,
'client_secret': clientSecret,
'redirect_uri': 'http://dash.mycompany.me',
'grant_type': 'authorization_code'
}
};
fetch('https://mycompany.harvestapp.com/oauth2/token', harvestHeaders)
.then( response => response.json() )
.then( token => {
console.log(token);
} )
}
componentDidMount(){
if( this.props.code !== 'none' ){
this.getHarvest();
}
}
Is there something here that I am doing wrong? Why does it always return a bad request? Any help would be appreciated. Thank you!
At least one issue you have is that when you use mode: 'no-cors' you’re telling the browser to handle the response as an opaque response, which means that you’re telling the browser to not make any properties of the response object accessible from JavaScript.
So if you make a mode: 'no-cors' request, response => response.json() is going to fail.
The only purpose for no-cors in practice is in combination with Service Workers when you’re just caching resources (e.g., images) from responses, without need to get properties of the responses.
Anyway, given that the client Web app making the requests in your deployment is running from a different origin than the server the requests are sent to, browsers are going to block the requests unless the server responds with the necessary CORS headers—Access-Control-Allow-Origin, for a start. For an explanation, see the MDN article HTTP access control (CORS).
That is, browsers block cross-origin requests made from JavaScript unless the server the requests are sent to opts-in to allowing those, with the Access-Control-Allow-Origin, etc., response headers. The reason Postman doesn’t block such requests is that Postman is not an arbitrary Web app running at some specific origin on the Web but is instead a browser plugin that you’ve intentionally installed. So it’s not bound the cross-origin restrictions browser enforce for Web apps.

Resources