Using response key from api as middleware in Laravel - laravel

I'm creating a web app & keeping my web client and backend API completely separate. I want to use the token from sign in api response for every url in my web app route as an middleware authentication. So if I don't have response from sign in api I cannot access the url.
I have sign in api like this, using username & password as header. I'm using this api when login to my web app:
$client = new Client();
$credentials = base64_encode('username:password');
$response = $client->get('sign-in-url',
[
'headers' => [
'Authorization' => 'Basic ' . $credentials,
],
]);
...
return $response;
My question is how to protect every url on my web app using that token? If it is in web app I usually using middleware to check if user already logged in or not. But what I need to do if using api?

You can define a middleware and put it's address inside $middleware array of your App\Http\Kernel class. It will be applied on every request (both web and api).

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"

Laravel's signedURL generates wrong URL when using api middlware

I have a front-end running on Nuxt and Laravel as a back-end service. When I generate the signedURL using the Laravel's API middleware - the path includes "api" in the URL, resulting into a page not found exception on the Nuxt side
So, here are the steps to better understand what's happening:
User clicks a button in Nuxt application and sends the ajax request to the Laravel API
API Controller generates the signedURL
$signedUrl = URL::signedRoute('register', ['email' => $this->request->email, 'group_id' => $this->request->group_id], null, false);
Generated URL includes the "api" in the path, which of course, cannot be accessed
http://localhost:3000/api/register?email=ss%40gmail.com&group_id=2&signature=ce4fba05bf5ccae6ea20a6043a47ca11de603238214deda7202d19f2989272cb
Is there a way to get rid of the /api/ from the generated URL? I've tried setting 4th param (absolute) in the method signedRoute to false, but it doesn't help.
The default api routes have prefix 'api' as seen in your RouterProvider:
protected function mapApiRoutes()
{
Route::prefix('api')
...;
}
When you generate the signed URL, for your route 'register' which is using the prefix api , the generated URL will be as expected: www.mydomain.com/api/register?...

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

How to authenticate API requests in Laravel?

I am currently building some sort of posts based web application using Laravel 5(.4). I have decided to load asynchronously the comment section for each post(and refresh it periodically). After some research I have decided to write a small integrated REST API (using the api routes of Laravel) that should answer to the requests made through AJAX.
However, I am facing the problem if authenticating the incoming requests. Take for example a request to post some comment. How exactly would you recommend to do that?
If you are making AJAX requests from browser and you are signed in then you don't need to use Laravel Passport tokens.
You can define certain routes which will be using web,auth middleware on requests like webapi/comments/get like this.
Route::group(['middleware' => ['web','auth]], function () {
Route::get('webapi/comments/get', 'CommentsController#get');
}
And use Auth Facade as you do in web request i.e Auth::check(), Auth::user() etc. and return the data in JSON like this.
class CommentsController extends Controller
{
public function get(Request $request)
{
if($request->acceptsJson()){
$data = array();
// add data
return response()->json([
"data"=> $data,
"status" => true
]);
}else{
return abort(404);
}
}
}
You can also send Accept header in AJAX request as application/json and in controller check if request $request->acceptsJson() and make your decision to show content when url is loaded from browser address bar or requested as AJAX.
Laravel Passport token are useful where there is no session and cookies are managed.
hope this helps :)
"Passport includes an authentication guard that will validate access tokens on incoming requests. Once you have configured the api guard to use the passport driver, you only need to specify the auth:api middleware on any routes that require a valid access token" - from the Laraven Documentation.
Apparently I have to configure passport, and after that configure the auth:api middleware to use the passport driver. Correct me if I'm wrong, please :)

Passport Auth Error when Accessing API Routes from Web

I'm using axios to request some data that requires that the user is logged in. I've tried a couple things to get the 401 to go but have had no joy yet. The API is on a subdomain and I think this might be why I'm having issues. I also have the session set to .domain.tld.
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class is in on the web middlewares. When I use the passport demo the authorization works just fine. However, when I send an axios request to an API route on the subdomain, it doesn't have any of the Set-Cookie headers that the demo sends to the web routes. I then tried putting in window.axios.defaults.headers.common['Authorization'] = 'Bearer (laravel_token here) with no luck as well.
How do I get my API endpoints (on the api subdomain) to work with Laravel's in-app Passport authentication?
It might be an issue with axios itself. Use Guzzle instead to opt out the possibility that its axios.
$http = new \GuzzleHttp\Client;
$response = $http->request('POST', 'your api url here', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$access_token,
],
'form_params'=>[
//if you have any data to send as a post request then put it here.
]
]);
Set your Accept parameter as well. Give it a roll.
Figured it out! Needed to enable withCredentials in Axios.
axios.defaults.withCredentials = true;

Resources