Premise · What you want to realize
I want to get json from API server using React's axios.
Front end: React.js
Back end: Laravel5.5
The authentication method uses Laravel default AUTH.
Since we want to return JSON only when logging in on the API side, we use middleware (auth) with Laravel routing.
Problems occurring · Error messages
If you hit api from the browser, it will be displayed normally, but if you go through React's axios you get the following error. 401 (Unauthorized)
It can be taken by accessing from the browser
Source Codes
■React.js
import axios from 'axios';
const host = window.location.protocol + '//api.' + window.location.hostname ;
const path = window.location.pathname
export const getIndex = nowId =>
axios
.get(host + '/v1/movie/' + nowId, {
headers: {
'Accept': 'application/json',
},
})
.then((results) => {
const status = results.status
if(typeof result === 'undefind'){
return status
}
const indexDatas = results.data[0]
return indexDatas
}).catch(
error => {}
);
■Laravel (API)
・/routes/web.php
Route::get('/auth/login/{token}', 'Auth\LoginController#auth');
Route::get('/auth/logout', 'Auth\LoginController#logout');
Route::get('/v1/sidemenu', 'ChallengersController#sidemenu');
Route::group(['prefix'=>'v1', 'middleware' => ['auth']],function(){
// Movie
// =======
Route::group(['prefix'=>'movie', 'middleware' => ['cors']],function(){
Route::get('/contents', 'MovieController#contents');
Route::get('/addContents', 'MovieController#addContents');
Route::get('/{id}/getChapter', 'MovieController#getChapter');
Route::get('/{id}/getReview', 'MovieController#getReview');
Route::get('/{id}/reviewCount', 'MovieController#getReviewCount');
Route::post('/postReview', 'MovieController#postReview');
Route::get('/review/commit', 'MovieController#reviewCommit');
Route::get('/{id}', 'MovieController#detail');
Route::get('/list', 'MovieController#index');
});
// Podcast
// =======
Route::group(['prefix'=>'audio'],function(){
Route::get('/list', 'PodcastController#index');
Route::get('/{id}', 'PodcastController#detail');
});
// Lecture
Route::group(['prefix'=>'lecture'],function(){
Route::get('/', 'LecturesController#index');
Route::get('/{id}', 'LecturesController#show');
Route::get('/{id}/schedules', 'LectureSchedulesController#index');
});
});
・/config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
],
Is the solution to this problem to give authentication information to the header of the request side (React's axios)?
Then, what kind of things should be put in the header?
I tried putting the same thing as the figure below, but it did not move.
API Header
axios
.get(host + '/v1/movie/' + nowId, {
headers: {
'Accept': 'application/json',
'Set-Cookie': 'laravel_session=eyJpdiI6IitBVldGM0VORzFZRk1ick1IY2Z5d1E9PSIsInZhbHVlIjoiT3JPeUVHc3BSaE5vRXF0KzB3N2xXRkdXb0xwMDVvS0RZR1VQM0xmMFkySnNrS01KRHVXMTFWNVhTU1wvMTVwa3RDRmNvajVMZGhiU2t4dFEzY1FxdkFnPT0iLCJtYWMiOiJjMjJhYWQ3ZjczMDgwOTExZDI5Njc5OTY4YTg5ZjgxMGI1MDlmYmNkZDJkZTFmNDA5YWMyZjRjOTYxYzc0YzNlIn0%3D;'
},
})
.then((results) => {
const status = results.status
if(typeof result === 'undefind'){
return status
}
const indexDatas = results.data[0]
return indexDatas
}).catch(
error => {}
);
your are able to open in browser, because you have added the routes in web.php.
in order to open from api , you have to add routes in api.php.
Related
my get route is returning a 401 unauthorized status code and undefined but everything works in postman so I'm assuming that this is isolated in my react and not a problem with my api. Using a bearer token for auth and can provide more of the auth code if needed. using mern stack
get route in the api file of my client-
export const getOneApplication = (user, applicationId) => {
return axios({
url: `${apiUrl}/application/${applicationId}`,
method: 'GET',
headers: {
Authorization: `Token token=${user.token}`
}
})
}
route from app.js-
<Route
path='/application/:id'
element={
<ShowApplication user={user} msgAlert={msgAlert}/>}
/>
get route from backend api-
router.get('/application/:id', requireToken, (req, res, next) => {
// req.params.id will be set based on the `:id` in the route
Application.findById(req.params.id)
.then(handle404)
// if `findById` is succesful, respond with 200 and "application" JSON
.then((application) => res.status(200).json({ application: application.toObject() }))
// if an error occurs, pass it to the handler
.catch(next)
})
The answer ended up being that I was not passing the user into the useEffect in the component, which when running the route caused me to lose the token and get the 401 status code
const [application, setApplication] = useState(null)
const {user} = props
const { id } = useParams()
console.log('id in showApplication', id)
// empty dependency array in useEffect to act like component did mount
useEffect(() => {
getOneApplication(user, id)
.then(res => {
console.log('this is the res', res)
setApplication(res.data.application)})
.catch(() => {
console.log('show failed')
})
}, [])
I'm having issue when I try to do an axios call whithin the scope of the response
const url = 'http://localhost:8000/session/';
axios.get(url).then(response => {
console.log(response)
const sessionEnCours = response.data.results.filter(session => session.fin_session == null).map(session => {
axios.get(session.client).then(client => {
session.client = `${client.prenom} ${client.nom}`
})
return session
})
sessionEnCours.map(session => console.log(session))
setSession(sessionEnCours)
})
}, []);
I have a Django API, so I have hyperlink models and get url as a foreign key. Whenever I'm trying to replace this url with the customer name with my little trick, it is not modified.
Thank you for your help
I am working on a user registration feature with frontend React and backend Laravel 8. When the input fields are valid it is working fine. But even if any of the input fields fail in the backend validation it throws an error saying "access has been blocked by CORS policy". Here is an image of the error. My question is why is everything working fine when the input fields are valid, but throwing an unrelatable error when it fails. And below is my code:
Frontend (React)
const register = async(values) => {
const {email, serial, password, confirm_password} = values;
const details = {email : email, serial : serial, password: password, password_confirmation : confirm_password};
try {
const result = await fetch('http://192.168.1.15:8000/api/v1/register', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(details),
})
const data = await result.json();
if (data.error) {
console.log(data.error)
}
else {
setUser(data.data)
cookies.set('Noortap', data.data, { path: '/' });
console.log(cookies.get('Noortap'))
}
}
catch (err) {
console.log(err)
}
}
Backend (Laravel)
public function register(Request $request)
{
$request->validate([
'name' => 'max:255',
'email' => 'required|unique:users,email|email|max:255',
'serial' => ['required','max:255', new IsValidSerialNumber],
'password' => 'required|confirmed',
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'is_admin' => 0,
'password' => Hash::make($request->password)
]);
\App\Models\Tag::where('serial_number', $request->serial)->update([
'assigned' => 1,
'user_id' => $user->id
]);
// // response
// return $this->login($request);
return $request;
}
That is because your frontend and backend are on separate "domains". In this case, they are on the same domain but a different port. You will need to add http://192.168.1.15:3000 to the $except array in app/Http/Middleware/VerifyCsrfToken.php so that you dont face a CORS policy issue.
So your file should look something like this:
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array<int, string>
*/
protected $except = [
'192.168.1.15:3000'
];
}
This is the API code to send the request. It works fine when I send it with only one parameter.
const handlecreate=(evt)=>{
evt.preventDefault();
const fd = new FormData();
fd.append('image', picture);
axios.post('http://127.0.0.1:8000/api/post/store',{fd,form});
)
}
In laravel as backend:
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'image' => 'required',
'category'=>'required',
'slug'=>'required',
'heading'=>'required',
]);
if ($validator->fails())
{
return response(['errors'=>$validator->errors()->all()], 200);
}
}
If we want to post the data with multiple parameter that is store in different state hooks then we have to append the each data of hooks
const handlecreate=(evt)=>{
const fd = new FormData();
fd.append('image', picture);
fd.append('heading',form.heading);
axios.post('http://127.0.0.1:8000/api/post/store',fd);
}
I would be answering the question in bit depth, so that it can help other as well with thorough understanding.
Note: Make sure you removed the cross origin issues if you are using react as front end or any other framework
Backend work
First you need to make the route properly in your laravel api located in laravel: routes/api
Let's assume we created the route in the api file and connected our controller likewise:
Route::post('/storeData', 'StoreController#store');
Now we need a controller on the same name in:
App/http/controllers/StoreController
In the StoreController we need the function which is connected that is store function in the StoreController:
public function store(Request $request)
{
$this->validate($request, [
'vin' => 'required|unique:autos,vin',
'lot' => 'required|unique:autos,lot',
]);
$autos = new Auto; //this is the model(mvc)
$autos->vin = $request->vin;
$autos->lot = $request->lot;
$autos->save();
return response()->json([
'success_message' => 'success auto is created',
], 200); // a message to the front end after successful execution of the query
}
Frontend Work
export const storeData = () => {
let axiosConfig = {
headers: {
"Content-Type": "application/json;charset=UTF-8",
Accept: "application/json",
Authorization: `Bearer ${decryptedToken}`, // if you had made the passport 0Auth2
}
};
const autoData = new FormData();
autoData.append("vin", autoData.vin);
autoData.append("lot", autoData.lot);
axios
.post(`http://127.0.0.1:8000/api/autoDataStore`, autoData, axiosConfig)
.then((response) => {
if (response.data.success_message) {
console.log(response.data);
} else if(response.data.error_message){
}
})
.catch((err) => {
console.log(err.response.data.errors)
});
};
I have React frontend and Laravel Backend Application which authenticates user using JWT. The login process is working properly and I can get the authenticated user with the me function of JWT. But now when I try to access contents based on the authenticated user, I get 401 error. I'm adding my react axios function and also my laravel controller that has the function which is giving the error. Please point out what am I doing wrong on it. Any help is very much appreciated. Thank you.
React axios function:
export const fetchMyApplications = () => {
return async dispatch => {
const url = `/auth/my-applications`;
var formdata = new FormData();
const token = getCookie("userToken");
const response = await api
.get(
url,
{
headers: {
Authorization: `Bearer ${token}`
}
}
)
.then(res => {
return res;
})
.catch(error => {
return error.response;
});
dispatch({
type: "FETCH_MY_APLICATIONS",
payload: response
});
};
}
Laravel controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use App\Models\Application;
class ApplyController extends Controller
{
public function __construct()
{
\Config::set('auth.providers.users.model', \App\Applicant::class);
$this->middleware('auth:api', ['except' =['personalDetails']]);
}
public function myApplications(){
try {
$user = auth()->userOrFail();
$applications = Application::where('applicant_id', $user->applicant_id)->with('course')->get();
return response()->json(['applications'=> $applications], 200);
}catch (\Tymon\JWTAuth\Exceptions\UserNotDefinedException $e) {
return response()->json(['status'=> false, 'errors'=> 'Unauthenticated User'], 401);
}
}
}
Auth Config:
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
],
Postman Checking Logged In User:
Postman Trying to get applications of logged in user:
I figured out what was wrong. Actually it was not with my code, rather it was apache configuration on linode server. I added authorization header to the apache config file and it worked.