Http status code 412 - Precondition failed - javascript

Getting 412 status code in response while trying to call restful service
While calling a restful service through ajax, I am passing authentication token in request header and a request body which is a json object. The response that I get from server is caught as 412 status code.
{"code":412,"status":"Precondition Failed","message":"User queryAll failed: Unexpected error parsing authentication token: 7d6f7d04-2b75-480d-8412-e6b9c173fb0e: Unable to convert authentication token to session: Unable to handle credentials from REST request body: [Authentication tag check failed. Message=ct5Rp34R2jgOlMUl29ElZg calculated=jwxpg_IzZKLrQACDM_D8pw]: [Unable to handle credentials from REST request body: [Authentication tag check failed. Message=ct5Rp34R2jgOlMUl29ElZg calculated=jwxpg_IzZKLrQACDM_D8pw]]: [7d6f7d04-2b75-480d-8412-e6b9c173fb0e: Unable to convert authentication token to session: Unable to handle credentials from REST request body: [Authentication tag check failed. Message=ct5Rp34R2jgOlMUl29ElZg calculated=jwxpg_IzZKLrQACDM_D8pw]: [Unable to handle credentials from REST request body: [Authentication tag check failed. Message=ct5Rp34R2jgOlMUl29ElZg calculated=jwxpg_IzZKLrQACDM_D8pw]]]","objectData":null}

Related

Get authorization token from headers into fetch reactj

I am using fetch in my react project to fetch data from an API which is authenticated using a token and my login end-point in the postman return the token in authorization header, you can see
and this's my login funtion in reactjs project
async login(dataLogin) {
const response = await fetch(`${API_URL}/login`, {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: dataLogin
});
const data = await response
console.log(response.headers);
console.log(response.headers.Authorization);
console.log(response.headers.get('Authorization'));
return data;}
you can see that response.headers.authorization return undefined and
response.headers.get('Authorization') return null.
and you can see in my browsers' Network panel
please anyone know how to get the authorization token from the headers?
When you are trying to login using API, then you should receive data i.e. Authorization token or anything else in the response of call.
Check what is the response you're getting when you called an API, it should probably be like
response.data
First you need to check the same in Postman.
To access value of response header server must return header name in Access-Control-Expose-Headers header. Without it Authorization is inaccessible in browser.
response.headers.get('Authorization')
Edit:
Since you are getting null, consider that:
The Authorization header is usually, but not always, sent after the
user agent first attempts to request a protected resource without
credentials.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
Therefore, instead of using postman, in order to see the response header, use the browsers' Network panel.

Unexpected end of JSON input while consuming Response body (self-defined HTTP codes)

I receive the following error when attempting to consume the body of a Response to a successful HTTP POST request:
SyntaxError: Unexpected end of JSON input.
This is the Express.js statement I used to send the response:
res.status(204).send(response)
Express's res.send() method automatically converts JavaScript objects to JSON upon sending. Regardless, response is explicitly being transformed into JSON via JSON.stringify() in its definition statement. So I am definitely sending JSON.
--
I am consuming the request on the client as follows:
fetch(URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data) // data is defined elsewhere in the file
})
.then(res => res.json())
.then(data => console.log(data))
However, whenever I attempt to read response.body to completion (see Body), I receive the following error:
SyntaxError: Unexpected end of JSON input.
Again, I have already confirmed that the data I wish to send from server to client is in JSON format. So, something is going wrong in-transit, as I am attempting to convert something to JSON that is not actually JSON.
I suspect the resource I wish to send is being misplaced in-transit, but I am not sure how.
Brother, you are sending the wrong status code actually 204 is used for when no content is access due to some reason when everything is ok then 200 status code is used.
res.status(200).send(response);
updated answer after comment.
res.status(400).json({
code : 400,
message: "error message string"
})
The issue was that I was self-defining my status code as 204.
When HTTP status 204 is specified, only the headers of your request will be forwarded. No body content will be forwarded.
Recall that my original Express response was:
res.status(204).send(response)
By defining HTTP status 204, I ensured that the response in send(response) would be discarded.
My issue was resolved by updating my response to:
res.send(response)

Make post request from js to django rest framework

I have a DFR api endpoint:
url = http://127.0.0.1:8000/x/y/
Url of the page running JS code: http://127.0.0.1:8000/x/z/1/
I have logged in as User1 in my browser.
POST request - from DRF browser api - good.
GET request - from javascript - good.
POST request - from javascript - 403 error.
So perhaps I dont know how to make an authenticated ajax request from JS. When I do the same request from browser api, may be the browser takes care of authentication.
My current js code:
axios({
method: 'post',
baseURL: window.location.origin,
url: '/x/y/',
// adding auth header also gives same 403 error for post request
// headers: {
// Authorization: 'Token e77b8ca898b51cde72dcf2aa2c385942d771e972'
// },
data: {
name: 'xyz'
},
responseType: 'json',
})
.then(function (response) {
console.log(' success');
})
.catch(function (error) {
console.log(' error=', error.message);
});
If you are on chrome browser, go in console ctrl+shift+j and then go in network.
When a post request is made, we can see the error message in this network tab.
My post request had following error:
"CSRF Failed: CSRF token missing or incorrect."
To add csrf token on axios ajax request put following lines of code at beginning of your js file:
axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
Are you appending the CSRF token in your request,CSRF can cause 403 errors.Try appending csrf token in request headers

Auth refresh token not working when the orgin request is a POST method

I have a js client (vuejs) and a backend using DRF both in local.
I use this package to generate the token : https://github.com/davesque/django-rest-framework-simplejwt
I use this package https://www.npmjs.com/package/axios-auth-refresh to handle refresh token logic.
The main goal is to intercept a request when it return a 401 response, perform a refresh token request and then resolve the orginal request with the new token.
It works when the original request is a GET request but not when it is a POST request.
When using a POST request :
The orgin request fall in 401 when the token expire then the interceptor occur but the server respond with 405 method not allowed:
-https://imgur.com/C1tchvb
the method from the request from the interceptor does not match the method in the code shown above (line 3 & 4) : as you can see the server receive the payload from the origin request as method of the request :
-https://imgur.com/nlAknMi
I found this post : App Script sends 405 response when trying to send a POST request
i try to change the headers as advised but it did not work
How is the payload from the orginal resquest becoming the method of the interceptor when the origin request is a Post request with a payload ?
Here the code from the javascript client :
const refreshAuthLogic = failedRequest => axios(
{
method: 'post',
url: 'auth/refresh',
data: { refresh: store.state.token.refresh }
}).then(tokenRefreshResponse => {
store.dispatch('refreshToken', tokenRefreshResponse.data)
return Promise.resolve()
})
const instance = axios.create({
baseURL: '/api/'
})
instance.interceptors.request.use(config => {
config.headers.Authorization = `Bearer ${store.state.token.access}`
return config
})
createAuthRefreshInterceptor(instance, refreshAuthLogic)
EDIT
I manage to get it work but i don't really understand:
the problem is related to DJANGO/ DRF and not axios
it seems that when a POST request is done and fail ( here with 401) the server keeped the data.
Here the part i can't explain :
when the request of the interceptor (to refresh token) hit the server, it messes with the data of previous request.
I had to add a middleware in django to clear the body when the request fails with 401 and it worked for me. But it is not a proper solution i guess.
Unfortunately the lib is loosely mantained and it's flawed in some aspects.
Eg: concurrent requests are not correctly queued when the request is sent with and invalid token but the response arrives when a new token is already issued.
As is, if you look at the lib source, you'll find in the very first lines:
/** #type {Object} */
const defaults = {
/** #type {Number[]} */
statusCodes: [
401 // Unauthorized
]
};
This means that only 401 code is managed and the statusCodes are not exported so them remains private.
If you want to continue to use this library you can fork it in order to change what does not fit with your stack or simply copy the source, edit it and use it as a local service.

Handling 401 Unauthorised responses with visionmedia/superagent

Background
I'm using visionmedia/superagent to access my REST API. The API is currently available on a different domain and has CORS setup to allow cross domain requests from my client. To access the API securely I pass an Authorization header with an access token. The token has a short life and when it expires I can make a request for a new one using a refresh token. When an access token has expired the server will respond with a 401 error to let me know the request was Unauthorised.
Problem
I am trying to catch the 401 Unauthorised request with superagent, then handle the token refresh. The problem is superagent is not returning a standard response or error for the 401. I get a string response instead of an object.
Error Response
Error: Request has been terminated
Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.
at Request.crossDomainError (client.js:616)
at XMLHttpRequest.xhr.onreadystatechange (client.js:724)
Call
ajax.get(api.baseURL + '/some_request)
.accept('application/json')
.set('Content-Type', 'application/json')
.set('Authorization', 'Bearer ' + this.getAccessToken())
.send({...})
.then((sucess) => {
//handle success, update data
})
.catch((error) => {
//handle error, if 401 refresh the token and try again.
});
Additional Information
The server is successfully handling the CORS side of things, the initial OPTIONS request is returning successfully with a 200.
I have tried using the non ES6 .end((error, response) => {...} method to handle responses with the same result.
I'm using superagent version "3.4.0"
I have tried catching the error event, get the same error string.
.on('response', (error, response) => {
//manage error
})
.on('error', function(err) {
//manage error
})
My server 401 response has a json response body, and returns a Content-Type:application/json; charset=UTF-8 header
{
"name":"Unauthorized",
"message":"You are requesting with an invalid credential.",
"code":0,
"status":401,
"type":"yii\\web\\UnauthorizedHttpException"
}
Question
What do I need to do to get access to the error object for a 401 response? I want to be able to check the error.status to see if its a 401 so I can refresh the token?

Categories

Resources