Django rest framework 401 error with React Axios - reactjs

Im working on a project with Django rest framework backend and React as frontend. Axios is used for http request and JWT for authentication. I issue im facing is that, after login and getting token django is throwing 401 error for every request. But this issue is resolved if header config is toggled for Axios.
Please find the below codes for your reference and help to resolve.
Thanks in advance.
DRF **settings.py**
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=1),
'REFRESH_TOKEN_LIFETIME': timedelta(days=2),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
'UPDATE_LAST_LOGIN': True,
}
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000"
]
**axios setup**
const axiosClient = axios.create({
baseURL: import.meta.env.VITE_API_URL,
headers: {
"Content-Type": "application/json",
},
});
export default axiosClient;
const jToken = useSelector((state) => state.authSlice.accessToken);
axiosClient.interceptors.request.use(function (config) {
config.headers.Authorization = `Bearer ${jToken}`;
return config;
});
**Axios request**
const fetchData = async () => {
try {
const response = await axiosClient.get(AppContext.managementStudentUri);
// console.log(response.data);
setData(response.data);
setIsLoading(false);
} catch (error) {
apiErrorHandler(error);
}
};

But this issue is resolved if header config is toggled for Axios.
The token is used for Authentification so once Login is done and token is generated, it should be sent with every request to identify the use.
But if it's not sent Django throws a 401 Unauthorized Error
https://www.django-rest-framework.org/api-guide/authentication/
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401

Related

CORS error while trying to post data with Axios on AWS REST API configuration using a node.js Lambda function

I'm posting data to a DynamoDB table with axios in a React front-end.
The API is set up through a serverless configuration with an API Gateway and Lambda on AWS.
While the request goes through and I see the added item on the database I still get a CORS error https://i.stack.imgur.com/m7yMG.jpg
This is the axios method:
import axios from "axios";
export const sendItemToDB = async (_data) => {
if (!_data) { return };
try {
const res = await axios({
method: "POST",
url: process.env.REACT_APP_QUERY_API,
data: _data,
headers: {
"Content-Type": "text/plain"
},
});
console.log("data returned from api", res);
} catch (error) {
console.log("Error sending File to db: ");
console.log(error);
}
};
And the API method on Lambda:
const createRecord = async (event) => {
const response = { statusCode: 200 };
try {
const body = JSON.parse(event.body);
const params = {
TableName: process.env.DYNAMODB_TABLE_NAME,
Item: marshall(body || {}),
};
const createResult = await db.send(new PutItemCommand(params));
response.body = JSON.stringify({
message: "Successfully created record.",
createResult,
});
} catch (e) {
console.error(e);
response.statusCode = 500;
response.body = JSON.stringify({
message: "Failed to create record.",
errorMsg: e.message,
errorStack: e.stack,
});
}
return response;
};
I based this configuration on this tutorial : https://github.com/jacksonyuan-yt/dynamodb-crud-api-gateway
I solved this following amazon documentation and reconfiguring the serveless deployment yml.
Serverless documentation on api gateway and lambda proxy integration here
Adding the missing headers to all lambda functions was essential.
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
};
Also testing that OPTIONS is working for the preflight:
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-test-cors.html
Just as Stavros noticed, the problem is that this is not a simple cross-origin POST method request (because it contains custom headers), so you need to tweak CORS settings of AWS API Gateway by adding
"POST, GET & OPTIONS" for Access-Control-Allow-Methods
"content-type" for Access-Control-Allow-Headers
You can do it through console like this
You also might need to add those headers in lambda like this
and it will work.

Laravel Sanctum with ReactJS SPA returns 401 Unauthorized after successful login

I can't find where am I wrong, I'm trying to retrieve user data from server, but 401 error returned instead. Route is protected with middleware, but after successful login it is still unauthorized, what could cause this or where am I missing something?
// ReactJS
const http = axios.create({
baseURL: 'http://127.0.0.1:8000',
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
withCredentials: true
});
async function getUser() {
const csrf = await http.get('/sanctum/csrf-cookie')
const login = await http.post('/login', {
email: 'admin#gmail.com',
password: 'secret'
})
const user = await http.get('/api/user')
}
useEffect(() => {
getUser();
},[]);
Here is the laravel things
SESSION_DRIVER=cookie
SESSION_DOMAIN=127.0.0.1
SANCTUM_STATEFUL_DOMAIN=127.0.0.1:8000 // 8000 is laravel port
Route
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
Cors
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login'],
'supports_credentials' => true

getting a status code of 403 from spotify web api when trying to fetch with OAuth 2.0 Token

I'm playing around with the Spotify Web API, and I'm trying to fetch my most played songs. I'm using the client credentials OAuth flow (you can read more about it at https://developer.spotify.com/documentation/general/guides/authorization/client-credentials/) to get an access token so that I can create requests. I'm getting the access token just fine, but when I try to fetch the data with the token, I'm getting a 403, indicating that my request is not being authorized.
Error code:
GET https://api.spotify.com/v1/me/top/tracks 403
I'm using React, so I'm fetching the data on page load with useEffect.
API File (spotify.ts)
import { Buffer } from 'buffer';
const clientId = "" // omitted for privacy
const clientSecret = "" // omitted for privacy
const getToken = async (): Promise<string> => {
const res = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64'),
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
scope: 'user-top-read',
}),
});
const data = await res.json();
return data.access_token;
};
const getMostRecentSong = async (token: string) => {
const res = await fetch('https://api.spotify.com/v1/me/top/tracks', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
const data = await res.json();
return data;
}
App.tsx
import React, { useEffect } from 'react'
import { getToken, getMostRecentSong } from './services/spotify'
const App = () => {
useEffect(() => {
const getData = async () => {
const accessToken = await getToken();
const data = await getMostRecentSong(accessToken);
console.log(data);
}
getData();
}, [])
return (
...
)
}
I've included my App.tsx file as well for convenience, but the only error I'm getting is with the request itself. Any help is greatly appreciated :)
The /me/top/{type} route requires the user-top-read scope, so using the Client Credentials flow will always result in an error. Here's a summary of the Client Credentials flow:
The Client Credentials flow is used in server-to-server authentication. Since this flow does not include authorization, only endpoints that do not access user information can be accessed.
Instead, you will need to use the Authorization Code flow and proxy the Spotify requests using a request mechanism that isn't restricted by CORS (e.g. a server or serverless function), or use the Implicit Grant flow which can be implemented without an additional cooperating process (you can do it all in your client React app).

Get the set-cookie header from response but it doesn't store in the browser

I am currently working on a project using Ionic React with .NET API for login process.
And this is the problem I am facing:
This is the Response Header of my post request
And when I try to look at the application cookie, it seems that it is not being set.
This is the application view which should see the jwt cookie has been stored.
I have already added these two params for my Axios post request but not work at all.
{withCredentials: true, credentials: 'include'}
Thank you for your time to look into my question or help!!!
Below are my request/response setting on the client-side and backend:
Axios request:
const api = axios.create({
baseURL: `https://localhost:7220/api/User`
})
api.post("/login", postData, {withCredentials: true, credentials: 'include'})
.then(res => {
console.log(res);
})
.catch(error=>{
console.log(error);
})
Controller:
Response.Cookies.Append(key: "jwt", value: token, new CookieOptions
{
HttpOnly = true
});
Response response = new Response { Status = true, Message = _LOGINSUCCESSFUL };
return Ok(response);
Program.cs:
builder.Services.AddCors(p => p.AddPolicy("corsapp", builder =>
{
builder.WithOrigins("http://localhost:3000").AllowCredentials().AllowAnyMethod().AllowAnyHeader().AllowAnyMethod();
}
)
);

how to send cookies with axios post method using react Js

I am using react js for front end and spring boot for backend process. I need to send cookies from front end to backend for which I am trying following approach using axios:
Frontend
async function submitPageData() {
try {
const jwttoken = {
headers: {
jwt: to12,
Cookie: token
}
};
const response = await axios
.put(
url,
{
id: pageId,
projectName: PROJECT_NAME,
title: title
},
jwttoken
)
.then(function () {
});
} catch (error) {
}
}
}
}
And receiving cookies at backend using #CookieValue annotation but as I checked and found that my request header is not carrying Cookie with it.
Please guide me, how can I send cookie from react js axios method so that I will able to receive it at backend.
Edit
const jwttoken = {
headers: {
jwt: to12,
Cookie: token,
withCredentials: true
}
Thanks in advance!
For some reason, using withCredentials as a header doesn't work for me either.
This to add it like that:
import axios from "axios";
axios.defaults.withCredentials = true;

Resources