Axios Post method authorization does not work - React - reactjs

I am developing a website [using React for front-end // Spring for backend] and in this website there is an admin panel. There is a button which lets other admins to add users to the database but I have a problem with axios' post method.
I checked so many different sources but couldnt find exactly what I am looking for. So here I am.
I get this error, 401 error code, unauthorized client, when using this syntax below
async addUsers(newData){
const headers = {
'Content-Type': 'application/json',
'Authorization': window.$auth
}
await Axios.post(
"http://localhost:8080/admin/addUser",
JSON.stringify(newData),
{headers: headers}
);
}
Before, I tried using a different syntax which I think is wrong, and with this syntax I get 415 error code: 415 error code, unsupported media type
async addUsers(newData){
await Axios.post(
"http://localhost:8080/admin/addUser",
JSON.stringify(newData),
{auth:window.$auth},
{headers: {'Content-Type':'application/json'}}
);
}
P.S: I tried to add User manually to database using Insomnia REST client and it successfully adds it and returns 200 Code.
Could someone help me with this problem, please?

Instead of sending authorization token with each request better add it as a default header. First check if token exist if it is exist add it
if(authorization_token){
axios.defaults.headers.common['Authorization'] = authorization_token;
}

It looks like this "authorization always returning 401 error code" was a known issue. Changing the complete syntax fixed it. Here is the site that I found the solution on https://github.com/axios/axios/issues/926
Here is the part of my code which that I fixed and now works:
async addUsers(newData){
await Axios({
method:'post',
url:'http://localhost:8080/admin/addUser',
data:JSON.stringify(newData),
auth:window.$auth,
headers:{'Content-Type':'application/json'}
})
}

Related

How to get a cookie outside getServerSideProps?

I have this code inside getServerSideProps which gives me the token value from a cookie named token:
const token = context.req.cookies?.token || null;
const auth = true;
//Then I sent the token to server
const settings = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': "Bearer " + token,
},
body: JSON.stringify({ "limit": "10" })
};
The cookie is a httpOnly cookie I receive from a post request sent with Set-Cookie header.
The thing is, I want to use the token not only in page components (getServerSideProps is only in page components). In other components I'd like to sometimes use functions that give me more data, let's say all the messages of the client - based on his token (I limit it to 10 in logs.js and I want to increase it in my inner component functions) . Is it safe to pass the token via props and then use it in my functions? I have logs.js component, which has another component named Messages, and inside the Messages component I want to call a function to get more messages but I am not sure whether it is safe or not because the idea of getting the token in getServerSideProps is that nobody can see it, or am I wrong?
If I am not wrong, what is the best way to get the token from the client-side in order to send requests inside inner components?
the idea of getting the token in getServerSideProps is that nobody can see it
Not really when it comes to cookies. Cookies will be sent to the browser so anyone can see it anyways. What you do with it in getServerSideProps is hidden, but the cookie itself is visible.
Because it's an httpOnly cookie, you can't access it with javascript on the client. So if you need the cookie value in javascript, you have a few options:
Read the cookie in getServersideProps and pass that value to your page and through to your components. This will work if you only need your components to read the cookie value.
Change to a { httpOnly: false } cookie which will allow it to be read (and written to) by javascript. I wouldn't do this if it has anything to do with security, because then anyone can not only read the cookie but could change it and do whatever they want with it.
You mentioned it's a token - the big question is: what is the token for in terms of security? You mention using it to determine if you should have more than 10 logs. Is that a business requirement? Would something bad happen (like you lose money, a breach, etc?) if someone manipulated it to show 20, 30, 1,000?
If your business needs to show the user only 10 except in the case where his/her token increases that limit, and you don't want the user to manipulate the limit, leave it as httpOnly, read it in getServerSideProps, and then pass the number to your component. Then, nothing can be manipulated or changed because the client can't mess with the token to unlock more logs.

GET Shift Preference Issue

Having an error when getting this API (https://learn.microsoft.com/en-us/graph/api/shiftpreferences-get?view=graph-rest-1.0&tabs=http)
Request header:
{'Authorization': 'Bearer eyJ**6MA', 'Content-Type': 'application/json', 'MS-APP-ACTS-AS': '53**76'}
Error Response: {'error': {'code': 'Forbidden', 'message': '{"error":{"code":"Forbidden","message":"The user identifier in the path does not match the one in the authorization token.","details":[],"innererror":{"code":"InvalidOAuthToken"}}}', 'innerError': {'date': '2020-10-06T13:53:08', 'request-id': '093**ad', 'client-request-id': '09**bad'}}}
And I have all permissions required for this.
Any Idea why is this?
I can easily reproduce your problem.
This error will occur if you use the wrong user_id or the token you use is not issued by the user. You can use https://jwt.ms/ to parse your access token and view oid Claims, which is your user_id and also Token issuer, you need to ensure that it is consistent with the user_id in your request path.
There is also a relatively simple method, you can directly use Graph Explorer to request this API (this requires you to log in).

Proxy doesn't work with fetch() in React.js

I've made a simple project in React; the client is running at port 3000, server at 3001.
If I launch localhost:3001/api/visitator/cars it works correctly, but when I make the GET Request on Client I have this error, on console http://localhost:3000/api/visitator/cars 404 (Not found).
I don't know why, but the request is done on port 3000 and not 3001, even if on package.json is present
"proxy": "http://localhost:3001".
This is the code in client/api:
async function askForCars(){
let url = '/api/visitator/cars'
const response = await fetch(url);
const carJson = await response.json();
if(response.ok){
console.log(carJson)
return carJson;
} else {
let err = {status: response.status, errObj:carJson};
throw err; // An object with the error coming from the server
}
}
There are two ways to solve this:
You have give the full path rather than relative path as your server lies on a different domain as ports are different. So your url variable value should be the domain name + uri + i.e. http://localhost:3001/api/visitator/cars.
The second way to solve this would be you need to add redirect rules on the server where you are hosting the app so that your every request having http://localhost:3000/api uri should be redirected to http://localhost:3001/api.
I think the quick solution would be the first one for now incase you don't have requirement to redirect api calls to actual server. Hope it helps.

Uncaught (in promise) Error: Request failed with code 405 POST AXIOS

I am trying to post data in my database but every time I do try to dod it I get a 405 error. Also python has an error saying that I am submitting an empty list. Please point me in the right direction to solve this problem.
const axios = require('axios')
let URL = 'http://127.0.0.1:5000/Walls/saveComments'
let HEADERS = { 'Content-Type': 'application/json' }
let data = {
'post': post,
'time': time
}
axios.post(URL,data, HEADERS)
.then(function (response) {
console.log(response);
})
// Axios Call to Save A Post in Backend
The HTTP 405 error means that the server does not allow the HTTP request method that the client sent.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405
The HTTP method you're using in the code example you shared is POST. Therefore, it seems that your server does not accept POST requests.
In order to fix this, either change the request method to something that is supported, or change the server to allow POST requests.

Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter..?

I am trying to send a PUT request to an amazonS3 presigned URL. My request seems to be called twice even if I only have one PUT request. The first request returns 200 OK, the second one returns 400 Bad Request.
Here is my code:
var req = {
method: 'PUT',
url: presignedUrl,
headers: {
'Content-Type': 'text/csv'
},
data: <some file in base64 format>
};
$http(req).success(function(result) {
console.log('SUCCESS!');
}).error(function(error) {
console.log('FAILED!', error);
});
The 400 Bad Request error in more detail:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>InvalidArgument</Code>
<Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message>
<ArgumentName>Authorization</ArgumentName>
<ArgumentValue>Bearer someToken</ArgumentValue>
<RequestId>someRequestId</RequestId>
<HostId>someHostId</HostId>
</Error>
What I don't understand is, why is it returning 400? and What's the workaround?
Your client is probably sending an initial request that uses an Authorization header, which is being responded with a 302. The response includes a Location header which has a Signature parameter. The problem is that the headers from the initial request are being copied into the subsequent redirect request, such that it contains both Authorization and Signature. If you remove the Authorization from the subsequent request you should be good.
This happened to me, but in a Java / HttpClient environment. I can provide details of the solution in Java, but unfortunately not for AngularJS.
For the Googlers, if you're sending a signed (signature v4) S3 request via Cloudfront and "Restrict Bucket Access" is set to "Yes" in your Cloudfront Origin settings, Cloudfront will add the Authorization header to your request and you'll get this error. Since you've already signed your request, though, you should be able to turn this setting off and not sacrifice any security.
I know this may be too late to answer, but like #mlohbihler said, the cause of this error for me was the Authorization header being sent by the http interceptor I had setup in Angular.
Essentially, I had not properly filtered out the AWS S3 domain so as to avoid it automatically getting the JWT authorization header.
Also, the 400 "invalid argument" may surface as a result of wrong config/credentials for your S3::Presigner that is presigning the url to begin with. Once you get past the 400, you may encounter a 501 "not implemented" response like I did. Was able to solve it by specifying a Content-Length header (specified here as a required header). Hopefully that helps #arjuncc, it solved my postman issue when testing s3 image uploads with a presigned url.
The message says that ONLY ONE authentication allowed. It could be that You are sending one in URL as auth parameters, another - in headers as Authorization header.
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:scavenger_inc_flutter/utils/AuthUtils.dart';
import 'package:scavenger_inc_flutter/utils/URLS.dart';
class ApiClient {
static Dio dio;
static Dio getClient() {
if (dio == null) {
dio = new Dio();
dio.httpClientAdapter = new CustomHttpAdapter();
}
return dio;
}
}
class CustomHttpAdapter extends HttpClientAdapter {
DefaultHttpClientAdapter _adapter = DefaultHttpClientAdapter();
#override
void close({bool force = false}) {
_adapter.close(force: force);
}
#override
Future<ResponseBody> fetch(RequestOptions options,
Stream<List<int>> requestStream, Future<dynamic> cancelFuture) async {
String url = options.uri.toString();
if (url.contains(URLS.IP_ADDRESS) && await AuthUtils.isLoggedIn()) {
options.followRedirects = false;
options.headers.addAll({"Authorization": await AuthUtils.getJwtToken()});
}
final response = await _adapter.fetch(options, requestStream, cancelFuture);
if (response.statusCode == 302 || response.statusCode == 307) {
String redirect = (response.headers["location"][0]);
if(!redirect.contains(URLS.IP_ADDRESS)) {
options.path = redirect;
options.headers.clear();
}
return await fetch(options, requestStream, cancelFuture);
}
return response;
}
}
I disallowed following redirects.
Used the response object to check if it was redirected.
If it was 302, or 307, (HTTP Redirect Codes), I resent the request after clearing the Auth Headers.
I used an additioal check to send the headers only if the path contained my specific domain URL (or IP Address in this example).
All of the above, using a CustomHttpAdapter in Dio. Can also be used for images, by changing the ResponseType to bytes.
Let me know if this helps you!
I was using django restframework. I applied Token authentication in REST API. I use to pass token in request header (used ModHeader extension of Browser which automatically put Token in Authorization of request header) of django API till here every thing was fine.
But while making a click on Images/Files (which now shows the s3 URL). The Authorization automatically get passed. Thus the issue.
Link look similar to this.
https://.s3.amazonaws.com/media//small_image.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXXXXXXXXXXXXXXXXXX%2F20210317%2Fap-south-XXXXXXXXFaws4_request&X-Amz-Date=XXXXXXXXXXXXXXX&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
I lock the ModHeader extension to pass Authorization Token only while making rest to REST API and not while making resquest to S3 resources. i.e. do not pass any other Authorization while making request to S3 resource.
It's a silly mistake. But in case it helps.
Flutter: if you experience this with the http dart package, then upgrade to Flutter v2.10!
Related bugs in dart issue tracker:
https://github.com/dart-lang/sdk/issues/47246
https://github.com/dart-lang/sdk/issues/45410
--> these has been fixed in dart 2.16, which has been shipped with Flutter v2.10!
https://medium.com/dartlang/dart-2-16-improved-tooling-and-platform-handling-dd87abd6bad1

Resources