Laravel Passport + VueJS: Unauthenticated error - php

I'm currently building a laravel 5.4 powered page to manage users. I've done all basic pages such as home, login, register, dashboard using blade templating engine. Now I'm building the User Management page. I've successfully implemented VueJS for this particular page. All components are working perfectly.
Now the problem I'm facing now is using Axios to get logged in user data from API route. At first I'm using usual api route to get auth()->user() data but it doesn't work.
I've learned that I must use Laravel Passport to do this API operation.
These are the steps I made after that:
composer require laravel/passport
php artisan migrate
php artisan passport:install
Added the Laravel\Passport\HasApiTokens trait to your App\User model
Called the Passport::routes method within the boot method of your AuthServiceProvider
Set the driver option of the api authentication guard to passport
Added the CreateFreshApiToken middleware to your web middleware group
Edited bootstrap.js file like the following :
window.axios.defaults.headers.common = {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
'X-Requested-With': 'XMLHttpRequest'
};
Axios Code :
axios.post('/api/getmydata', {
params: {
type: 'raw'
}
})
.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
Changed route (api.php) :
Route::group(['middleware' => 'api'], function(){
Route::post('getmydata', 'ApiController#test');
});
Added function inside ApiController :
public function test() {
$user = Auth::user();
return $user;
}
The problem here is axios somehow return error: Unauthenticated
Is there anything wrong with my code?
Or is there any other way of achieving this? Thank you

Send the access token in the header of your API request:
Application Type :application/json
Authentication : Bearer [Access-Token]

Related

Laravel Sanctum returning 401 when trying to get the authenticated user

I want to get the currently logged in user whenever my React SPA starts, so I can show the user's information, but every time I try to get it from my Laravel back-end I get a 401.
I am using Laravel + Sanctum for my API, and using React in a different project for the front-end.
BACK-END:
I have the following in my AuthController controller:
public function user()
{
return auth()->user();
}
Inside my routes api.php I have the following route:
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::get('/user', [AuthController::class, 'user']);
Route::post('/logout', [AuthController::class, 'logout']);
});
My .env file contains the following:
SANCTUM_STATEFUL_DOMAINS=localhost:3000
SESSION_DOMAIN=localhost
FRONT-END:
I have a context that has the following:
useEffect(() => {
apiClient()
.get("/api/user")
.then((res) => {
setUser(res.data.user);
});
}, []);
and if you are wondering, my apiClient() comes from here:
import axios from "axios";
const apiClient = () => {
const api = axios.create({
baseURL: "http://localhost:8000",
withCredentials: true,
headers: {
Accept: "application/json",
},
});
return api;
};
export default apiClient;
This context is at the top level of the application.
I am not sure what's going on, my route /login is working as expected, I send the request and receive the user information as response which I set to a React state. On page refresh this state is removed because that's how Javascript works. I want to set it again using the useEffect mentioned above, so when the user loads the web app after closing the browser they can still see their information.
Thanks in advance!
To authenticate your SPA, your SPA's "login" page should first make a request to the /sanctum/csrf-cookie endpoint to initialize CSRF protection for the application:
axios.get('/sanctum/csrf-cookie').then(response => {
//Login...
});
For more information check https://laravel.com/docs/8.x/sanctum#spa-authentication

/pusher/auth endpoint returning 404 in Laravel

I have built a Laravel app where I am trying to implement Web Sockets via Pusher.com (for the first time).
While I have got public channel subscriptions working fine, I am struggling getting private channels working correctly.
According to the laravel documentation you need to uncomment App\Providers\BroadcastServiceProvider::class in app.php config file which I have.
My channels.php has the following rule(s)
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('private-queue.business.{business}', function ($user, Business $business) {
// #todo: add real authentication
return true;
});
Is there anything else I need to add to get /pusher/auth endpoint working?
As of Laravel 7.x, the Broadcasting endpoint is broadcasting/auth and not pusher/auth.
I needed to update my JS like so to be able to define a custom auth endpoint:
const pusher = new Pusher('{{ env('PUSHER_APP_KEY') }}', {
cluster: '{{ env('PUSHER_APP_CLUSTER') }}',
authEndpoint: '/broadcasting/auth',
auth: {
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
}
}
});
You will need to add the CSRF-TOKEN otherwise you will get Page Expired errors.
Could you try:
Try this:
Uncomment App\Providers\BroadcastServiceProvider::class in config/app.php
Use php artisan config:cache
Use php artisan route:cache
Check new route broadcasting/auth with php artisan route:list
Source

Laravel Pusher VueJS http://localhost:8000/broadcasting/auth 404 (Not Found)

I'm trying to implement right now in my project a real time notification ui using laravel broadcast. I already made it work by broadcasting on a public channel but once I switched on to a private channel, the error POST http://localhost:8000/broadcasting/auth 404 (Not Found) appears when loading the page.
Here's what I made sure to check so far:
I've already uncommented both the App\Providers\BroadcastServiceProvider::class and Illuminate\Broadcasting\BroadcastServiceProvider::class, in the config\app.php,
I've also included Broadcast::routes(); and tested Broadcast::routes(['middleware' => 'auth:admin']); inside the boot() method of Providers\BroadcastServiceProvider if it'll work but still no dice,
I've also tried passing the Broadcast::routes(); in routes\web.php and,
Made sure that I have included <meta name="csrf-token" content="{{ csrf_token() }}"> in the main app.
The project that I'm working on implements SPA using Vue JS which is completely separated from the backend and is only connected through api. I hope someone could give me an insight with what going wrong with my methods. Thank you!
The question was asked a long time ago, but I hope it will be useful to someone. I had the same issue using stand-alone SPA (Vue.js) and REST API (Laravel). To simplify implementation of live comments system I used laravel-echo and pusher.js. To solve the issue I specified the auth endpoint according to the "Customizing The Authorization Endpoint chapter"
https://laravel.com/docs/8.x/broadcasting#customizing-the-authorization-endpoint
I used the following approach:
authEndpoint: process.env.VUE_APP_API_ROOT + '/broadcasting/auth'
where VUE_APP_API_ROOT is "http://api.yoursite.dev
But then I got a new issue with CORS. I used JWT authentication for API endpoints and a middleware from the https://github.com/fruitcake/laravel-cors package that allows to specify 'Access-Control-Allow-Origin' headers to solve the CORS issue when SPA sends requests to the API from a different domain.
So to solve the CORS and authentication issue I added the broadcast routes to api.php and set the JWT auth middleware
Broadcast::routes(['middleware' => ['auth.jwt:api']]);
and set a custom Pusher authorizer using Laravel echo
window.Echo = new Echo({
broadcaster: "pusher",
cluster: process.env.VUE_APP_PUSHER_APP_CLUSTER,
encrypted: true,
key: process.env.VUE_APP_PUSHER_APP_KEY,
authorizer: (channel, options) => {
return {
authorize: (socketId, callback) => {
axios.post(process.env.VUE_APP_API_ROOT + '/api/broadcasting/auth', {
socket_id: socketId,
channel_name: channel.name
})
.then(response => {
callback(false, response.data);
})
.catch(error => {
callback(true, error);
});
}
};
},
})
P.S. To provide axios with JWT token I used axios interceptors that allows to get token from Vuex.
axios.interceptors.request.use(config => {
const token = store.getters['auth/accessToken'];
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
});

Laravel route api without api key and csrf token

Currently I have
Route::filter('pre_api', function($route, $request)
{
}
to do the api key validation and its working fine.
Is it possible to make a plain request to route api which allow client access to api without api key?
You can write api requests in routes/api.php.
You need to install the cors package in laravel.
toutrial for install core -> https://medium.com/#KrishaWeb/cross-origin-request-blocked-error-in-laravel-5-5-a733232795e4
example :
Route::group(['middleware' => 'cors'], function() {
Route::get('/hello',function(){
return 'hello';
});
});

Get to work with the authenticated guard in laravel API

I have a session login system for a few guards. I'm using Vue a lot and I came to the point where I need authentication in Vue in order to fetch and post data properly. The question is how could I get the authenticated session user to work with API. So in api.php I want to use a controller whose Middleware the authenticated user. I don't want to use Passport because I only have logins over the webpage and not API.
vue supports component also there is something called props which they are data that you can pass to your vue component what I would usually do is pass the authenticated user id to my vue component and then when I ever fire a request from vue component I will pass the current authenticated user to the backend and there I check if the id received with request is the same as the current authenticated user.
check the example below I will use the regular guard
loading vue component from blade
//loading vue test-component and pass the authenticated user
<test-component :authuser="{{Auth::(user)->id}}"></test-component>
vue component
<script>
export default {
props : ['authuser'], //should be the same name as you passed it
data(){
return {
}
},
created(){
axios.post('/api/test' , {
'authuser' : this.authuser
})
.then(res => {
console.log(res);
})
.catch(err => {
});
}
}
Api route
use Auth;
Route::post('api/test' , function($request){
if(Auth::user()->id == $request->authuser)
return 'you are authenticated';
else
return 'you are not authenticated';
});
Hope you find this helpful , Good luck.

Categories