We want to create a consumer web app for our API developed using Laravel Passport and Dingo API. Laravel has it’s built in webpack for Vue and ReactJS so we can nicely integrate our client app into existing project.
Here you can find final updated result containing views for:
https://github.com/danielcrt/laravel-reactjs-passport-authentication
Setup ReactJS inside Laravel project.
php artisan preset react
This will remove unnecessary files and prepare the project structure for a React app. You can see in your root directory a file webpack.mix.js
where are defined the paths for compiled folders and files.
mix.react('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
So all JS/JSX files from public/js
will be compiled to app.js
. The same will happen for CSS files.
We want all routes to be handled by React so in routes\web.php
we must have:
Route::view('/{path?}', 'home')
->where('path', '.*')
->name('react');
This is telling Laravel that for all routes it should return the home view found in resources\views\home.blade.php
. In this file it is important to include our compiled CSS and JS files.
<head>
...
<link rel="stylesheet" href="{{ asset("css/app.css") }}" type="text/css">
</head>
...
<script type="text/javascript" src="{{ asset("js/app.js") }}"></script>
</body>
In our resources\js\app.js
the bootstrap.js
file is required by default. And along that we should require our entry point into the app. In bootstrap file are included jQuery library and bootstrap js files. If you don’t plan to use them you can remove these to lower the build size.
Below that you have some important lines adding X-Requested-With
and X-CSRF-TOKEN
headers to axios. If you plan not making requests using axios than you have to handle the by your own. You can prepare the CSRF token for later use in Javascript adding following lines to your view:
<script>
window.Laravel = {!! json_encode([
'csrfToken' => csrf_token(),
]) !!};
</script>
We have used Redux in order to have access to user’s state all over the app so we wrapped our application in a Provider
in js\components\App.jsx
.
In js\helpers
we have added withCredentials = true
to axios configs. This will ensure that the authentication cookie will always be send back to the server. In order to handle the case when user wants to access protected routes without being authenticated we created a interceptor which will remove the local stored variable which tells us if user is logged in (for client side usage) and redirect him to home page.
axios.defaults.withCredentials = true;
axios.interceptors.response.use(
response => response,
(error) => {
if (error.response.data.status_code === 401) {
// we already know from the server that user is no longer logged in
// just delete the local field
localStorage.removeItem(GlobalConstants.USER_KEY);
history.push('/');
}
return Promise.reject(error);
});
That’s pretty much it. I feel these were the key elements which could save your development time.
If you’d like me to detail more the project structure and components just let me know in comments section.
Nice job. I actually want to capture the essential idea on how to use Laravel Passport from which the APIs are consumed by React app in the frontend.
I find your version contains a lot of refactoring both in backend and frontend that may confuse relative new guys like me. But alright, overall I can grasp the essential idea, although I couldn’t pay attention to details of the Redux parts, because I am still lack in Redux.
But when I try the app in Chrome by providing my url : http://localhost/mylaravelprojects/passportauth2/public/
it results in a blank page.
When I open DevTools, there is a warning :
DevTools failed to parse SourceMap: http://localhost/mylaravelprojects/passportauth2/public/js/react-router.js.map
I use React-Router version 5, because with version 4, it also resulted a blank page, but with different warnings which related to the use of componentWillMount() in React-Router version 4.
Thanks for your feedback Alexander!
You are right. There are lot of refactoring in there, some taken from the referenced repository.
Also the code regarding Redux is a bit clumsy.
I am preparing a new post with a simplified authentication without using Passport. Passport is usually too much for small/medium applications.
So the forthcoming post might fit better for you as the code will be cleaner.
In order to start the app you have to run in command line:
php artisan serve
and run your project at:localhost:8000
Thanks a lot for this article it’s really helpful. I have just one question. What is the purpose of
PERSONAL_CLIENT_ID=1
PERSONAL_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
PASSWORD_CLIENT_ID=2
PASSWORD_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
in the .env file? And should I set them up from oauth_clients table?
When you install Passport in your project, using:
php artisan passport:install
It will generate you those secret keys which must be stored in
.env
file. Those are used by Laravel Passport under the hood.