Vue.js + Laravel SPA - Socialite stateless Facebook Login - laravel

First to say that I already implement session based facebook login with laravel socialite and I registered proper facebook acc for developers and create app, but because of SPA I need to change to stateless solution...
The redirect throws "Response for preflight is invalid (redirect)" and check the following config, images and code...
My vue.js app works on localhost:8080 and backend laravel app on localhost:8000
I installed barryvdh/laravel-cors an
d implement standard login with JWTToken
I already install laravel socialite
So, I setup config/services with proper credentials already
'facebook' => [
'client_id' => 'xxxxxxxx',
'client_secret' => 'xxxxxxxxx',
'redirect' => 'http://localhost:8000/login/facebook/callback',
]
I also register a good routes and I tested them 1000 times...
And when a GET send request it cannot be redirected on fb because of Response for preflight is invalid (redirect):
SocialiteController
public function redirectToFacebookProvider()
{
return Socialite::driver('facebook')->stateless()->redirect(); // this throws error !!!
}
the error which I get in console is like on picture
It should open to me a popup to login on facebook ?
Why I have trouble with this redirect ?
Any help ?

Related

Laravel Jetstream/Sanctum API authentication

I have been working with Laravel since version 5.X up to version 8.X but always use it for backend API (never used blade template), and always pair it with VueJS on the front-end using JWT authentication (also never messed with any other authentication method).
Now with Laravel 9 and Vue 3, Im trying to use native Laravel Jetstream that uses SANCTUM and Vue+Inertia JS, and I'm quite lost with the authentication process. with JWT method, once the user succesfully login on the browser, all api request to Laravel will be authenticated using Authoraziation header. but this seems a different case with Sanctum.
After deploying and installing Jetstream and completed all the set-up. I created a user and loggedin with that user details. and I notice few things, there is a default API route
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
when I tried to directly access my.domain/api/user I notice it was redirected to GET /login
then redirected again to GET /dashboard
I then created a test api route using below
Route::get('test', function( Request $req) {
dd( [
'test' => $req->all(),
'user' => auth()->user(),
'request' => $req
] );
});
and I notice this request is not authenticated even when the cookies is present on the request as Im when I'm alraedy logged-in on the same browser, the auth()->user() is null.
I tried adding auth:sanctum middleware
Route::middleware('auth:sanctum')->get('test', function( Request $req) {
dd( [
'test' => $req->all(),
'user' => auth()->user(),
'request' => $req
] );
});
but having sanctum middle behave the same as the api/user where if i open api/test directly on the browser, it gets redirected to GET /login then redirected again to GET /dashboard and I'm quite lost at this point. I tried reading the docs and it says I have to do a separate authentication for this that would issue an API token and I was thinking I might better be going back with using JWT auth as it seems a lot easier to deal with.
So my question is; How can I authenticate an API end-point without having to redirect it to /login then /dashboard if the user is already logged in on my application using default sanctum authentication.
My goal is just to simply create /api/test that will be automatically authenticated if user already loggedin on the same browser and return the data I set on its return value and not doing any redirects.
Appreciate any help
I have got the same issue with laravel8
Jetstream and inertia vue3.
Am looking for the solution since 3 days posting messages on discord, searching on YouTube and more but nothing.
When i make an api call from your SPA to laravel, i got UNAUTHENTICATED response.
on postman you need put
headers
Accept = application/json
this tells your application know how works with Json
and go stop redirect to "Login"

Getting 401 after successfully authenticate on Laravel

I have this backend application running on Laravel 7.23.2 where I used tymondesigns / jwt-auth 1.0.0. The application is running on Linux.
The frontend is using Vue. The authentication happens just fine, I get the jwt token. After a successful authentication the frontend does several api calls passing the token in head, but I keep getting this 401 error. The same code works just fine on my local computer.
I did change the jwt_secret and clear the cache, but still not working.
Route::group(['middleware' => 'jwt.auth', 'namespace' => 'API'], function() {
Route::get('/com/page/{pageSize}', 'ComController#all')->middleware('role:Admin');
Route::get('/com/pesquisa/{anoMes}/{pageSize}', 'ComController#findByAnoMesAndFilters')->middleware('role:Informante|Gerente|Admin');
This is just a snapshot of my api.php file.
Does any one would have any idea what could be the main issue?
Let me know if further information is needed.
I´m also using https on the backend production, on localhost I use http.

Using Sanctum with regular Laravel authentication

I have a simple web app using regular authentication for all of my web routes. There are just a few places in my app where I want to be able to call a few API routes from Javascript. Can I setup Sanctum's SPA authentication to work without doing an SPA-style login?
I have followed the instructions server-side, and on my login page I am doing a CSRF cookie request using the axios library before the user logs-in using the standard routes. But when I try to then hit a Sanctum protected route I just get redirected to the home page.
Is it expected that Sanctum session-based auth should work with a regular app login?
Edit
I located the problem. In EnsureFrontendRequestsAreStateful is this function:
public static function fromFrontend($request)
{
$referer = Str::replaceFirst('https://', '', $request->headers->get('referer'));
$referer = Str::replaceFirst('http://', '', $referer);
return Str::startsWith($referer, config('sanctum.stateful', [])) ||
Str::is(config('sanctum.stateful', []), $referer);
}
$referer is null on my requests, so this function cannot return true. If 'referer' is changed to 'host' it works. Is this acceptable? Does it satisfy the point of the function still, that the "given request is from the first-party application frontend" or are there security implications I haven't considered?
'Referer' works when hitting the API endpoint from Javascript, but when hitting it from Postman or in a browser window the headers non-existence causes a problem. So in simple GET testing it is redirecting to login, but is working fine when called from the Axios library in a Vue component.
'Referer' works in postman too, you need only add header to your request Referer -> {{host}}. host it's postman variable or you can type it like localhost. Sanctum by default checking this referers localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1, but you can specify your own referer by adding variable to env file SANCTUM_STATEFUL_DOMAINS=your-app-domain.com here.

Laravel combine Passport authentication and normal authentication

How do I combine Passport authentication and normal laravel authentication?
I want the user to be logged in on pages of web-middleware and api-middleware. The login route is in api-middleware. Currently I have set up Passport authentication and it works fine for all api-middleware routes. How to make the user logged in in web-middleware as well?
Edit #1
What Im doing:
Login code
$http = new \GuzzleHttp\Client();
try {
$response = $http->post(config('services.passport.login_endpoint'), [
'form_params' => [
'grant_type' => 'password',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'username' => $args['email'],
'password' => $args['password']
]
]);
$user = User::where('email', $args['email'])->first();
Auth::guard('web')->login($user);
return [
"token" => $response->getBody()->getContents(),
"user" => $user
];
} // ...
Somewhere in some web-middleware route
return auth()->check() ? "logged in" : "not logged in";
returns "not logged in"
Ideally you shouldn't, as passport auth is for a separate app communicating to the API and laravel preshipped auth is for MVC, they are separate user sessions.
But assuming you know what you are doing, either call Auth::login($user); on user login via API, or generate the passport token when the user login through web middleware auth, whichever login happens first...
Remember Auth::login($user); creates a user session and sets cookies to refer to that session... So you create for yourself a new problem were on logout, there are two places to logout from... as technically the user is logged in twice, with passport token and with a cookie referring to his session...
Actually I'm in a situation like you were. I have searched a lot about it. I always needed web authentication because of nature of my projects but in addition I started to develop projects with api backend soo late in comparing with web development world.
I'm a bit lazy so I generally use Laravel Passport and without working always out of the box, it does the job so in my opinion if you want just the functionality of access tokens for api security, put your user login authentication on web side and just authenticate the api endpoints with auth:api middleware in your api.php file.
I know that that's not the best practice but since it sounds that you are not developing a pure Laravel SPA then you can follow the route for Laravel Multipage application with Vue powered.
But believe me best way is to use either web authentication or api authentication not together then as the above answer says, you will have two authentication working at the same time which does not sound ok.
At the end, when you want to get the authenticated user on blade templates you will use
auth()->user()
but on the other hand in api controllers you should use
auth('api')->user()
which is nice to have but dangerouse to use.
If you need to log an existing user instance into your application, you may call the login method with the user instance.
Auth::login($user);
You can also use the guard() method:
Auth::guard('web')->login($user);
See the documentation here for more information: https://laravel.com/docs/5.8/authentication#authenticating-users

Laravel passport 500 internal server error on EC2

I'm building an app using Angular 2 (no known as 4) as frontend and Laravel 5.4 as API backend. I'm using Laravel's passport password grant feature to authenticate user access to API.
The Frontend is not directly accessing oauth routes. My custom auth controller is talking to oauth/token to get the grant values.
This setup is working perfectly fine in my local environment, but in AWS EC2 it throws 500 internal server error.
I thought it could be related to GuzzleHttp\Client, but it was not. Even if I try to access oauth/token directly from Postman, it still throws 500 internal server error.
private function getPasswordGrant($username, $rawPassword) {
$http = new HttpClient();
$url = url('/') . "/oauth/token";
return $http->post($url, [
"form_params" => [
"grant_type" => "password",
"client_id" => config("auth.oauth_password_grant_client_id"),
"client_secret" => config("auth.oauth_password_grant_client_secret_key"),
"username" => $username,
"password" => $rawPassword,
"scope" => "*",
],
]);
}
This is the function in my custom Auth Controller which requests for password grant after the user being authenticated in another method (login and signup).
Most amazing thing is there's nothing logged in either laravel or apache logs.
Alright, after a lot of struggle and debugging. It turned out to be apache was unable to write into storage/logs/laravel.log and causing this problem. After giving appropriate permissions to storage/ folder everything is working as expected.

Resources