Open homeoftheunits opened 5 years ago
you can use middleware web etc for that .And use auth:web middleware for authentication. For part you need jwt use api and auth:api
@shirshak55 would you be able to provide an example of this? I am trying to achieve the same thing for 2 days now and I can't. For me it all depends on what I put in the /config/auth.php file. if defaults->guard => api
then my api login routes work but the web ones dont, and it's vice-versa if I put defaults->guard => web
Thanks!
@LastxTemplar hmm have you set auth:api and api middleware for api related routes?
the best option is to put web by default and use middleware api explicitly :)
hey @shirshak55
thanks for the response. That is exactly what I wanted to do. Basically I have a fresh Laravel 5.7 installation, and I use "tymon/jwt-auth": "^1.0.0.rc3"
for the jwt package.
Here is my config/auth.php:
[...]
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
[...]
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
Here is my routes/api.php
Route::group(['middleware' => ['api']], function () {
// User
Route::post('/user/login', ['as'=>'api.user.login', 'uses' => 'ApiAuthController@login']);
Route::post('/user/register', ['as'=>'api.user.register', 'uses' => 'ApiAuthController@register']);
});
And here is my ApiAuthController.php
class ApiAuthController extends Controller
{
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login']]);
}
public function register(Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required|string|min:3|max:255',
'phone_number' => 'nullable|numeric|digits_between:4,20',
'email' => 'required|email|max:255|unique:users,email',
'password' => 'required|string|min:6|confirmed',
]);
if ($validator->fails()) {
return response()->json(['validation_errors' => $validator->errors()], 401);
}
$user = new User();
$user->name = $request->name;
$user->email = $request->email;
$user->phone_number = $request->phone_number;
$user->password = Hash::make($request->password);
$user->save();
$token = NULL;
$credentials = request(['email', 'password']);
if (! $token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return response()->json(['message' => "Successfully Registered!", 'user' => $user, 'token' => $token], 200);
}
public function login()
{
$credentials = request(['email', 'password']);
$token = NULL;
if (! $token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
$user = auth()->user();
$token = auth()->tokenById($user->id);
return response()->json(['user' => $user, 'token' => $token], 200);
}
I used php artisan make:auth
after I made the fresh Laravel installation so I haven't touched any of the Auth Controllers that Laravel created.
With this current setup I am now able to login from the webpage but when trying to login through the API by posting to http://xxx.local:8888/api/user/login
I get this error:
"message": "Method Illuminate\\Auth\\SessionGuard::tokenById does not exist."
Now, if I change my config/auth.php
to this:
[...]
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
I can now login successfully through the API but if I go to my browser and try to login, I just get redirected to the login page without actually being logged in.
It seems to me that the framework does not handle correctly the default values in the config/auth.php
, at least that's my guess.
Thanks in advance for your help!
for api route use api guard bro.
auth('api')
Or
\Auth::guard('api')::attempt(...............)
Otherwise auth() will use web which don't work with api. I am using web route and jwt is working perfectly
Here is my sample authenticate controller
<?php
namespace Shirshak\User\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login']]);
}
/**
* Get a JWT token via given credentials.
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\JsonResponse
*/
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if ($token = $this->guard()->attempt($credentials)) {
return $this->respondWithToken($token);
}
return response()->json(['error' => 'Invalid Login Details'], 401);
}
/**
* Get the authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
return response()->json($this->guard()->user(), 200);
}
/**
* Log the user out (Invalidate the token).
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
$this->guard()->logout();
return response()->json(['message' => 'Successfully logged out']);
}
/**
* Refresh a token.
*
* @return \Illuminate\Http\JsonResponse
*/
public function refresh()
{
return $this->respondWithToken($this->guard()->refresh());
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => $this->guard()->factory()->getTTL() * 60,
]);
}
/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\Guard
*/
public function guard()
{
return Auth::guard('api');
}
}
Oh wow, this actually worked! Thank you so much!
Although I don't understand this too well, admittedly I am new at using guards, but when we are setting
$this->middleware('auth:api', ['except' => ['login']]);
doesn't this mean that it should use this guard from the config/auth.php
?
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
@LastxTemplar Think middleware like onions. When user hit the router first thing is it passes from middleware.
$this->middleware('auth:api', ['except' => ['login']]); means the route which is hitting this controller requires authentication with driver api. If not then it throws invalid message.
auth('api') means use api based authentication manager so auth('api')->check() means using use api based which you have set
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
If you dont use anything it uses default guard so auth() means auth('default_guard_name') Its not that complex :)
Thanks, makes more sense now :)
@shirshak55 @LastxTemplar I was stuck at this as welll... but now what happened is I have auth::api() in my middleware. If I pass token the it works fine ... but i have a route whose controller checks if user is authenticated() or not.. If I pass auth:api it will authenticate and I can check for auth() in my controller if I dont pass authorization it blocks it what should I do ?
@rakeshshubhu pass api middleware so you can use auth()->check()
. i mean api
not auth:api
@shirshak55 would you be able to provide an example of this? I am trying to achieve the same thing for 2 days now and I can't. For me it all depends on what I put in the /config/auth.php file. if
defaults->guard => api
then my api login routes work but the web ones dont, and it's vice-versa if I putdefaults->guard => web
Thanks!
Hi, My Friend When you using "default" guard for "web" and you want to user "api" for api routes, in ApiAuthController, you must use auth('api) to get true result!
@mratwan Yes saying same if u use default guard as jwt u can use auth()->check()
.
But most people use web as guard so I recomment using auth()->guard('api')
Or auth('api')
By the way we will need to set middleware to api otherwise we may get unexpected result.
Hi @shirshak55 ! Do you know about error Method Illuminate\Auth\RequestGuard::attempt does not exist ? I think it's related with this thread, I cannot access that method, do you have any solution? I already read it in other thread but no one can fix it. Thanks!
@athallara check ur config auth file and what is the value?
@shirshak55 Here it is..
`<?php return[ 'defaults' => [ 'guard' => env("AUTH_GUARD", "api"), 'passwords' => 'users', ], 'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], ], 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], ],
] ?>`
it looks good. did u use middleware: api?
@shirshak yeah sir, I already do that :(
@athallara hmm can u show me how is ur routes files?
@shirshak55 here sir, fyi i'ts rest api using lumen 5.8.6 .. is there any different configuration for it?
`$router->group([ 'prefix' => 'v1', 'middleware' => 'api' //if this commented still doesn't work ], function () use ($router){
//Authentication
$router->post('register', 'Auth\AuthController@register');
$router->post('login', 'Auth\AuthController@login');
});`
do composer dump-autoload -o
.
'middleware' => 'api' //if this commented still doesn't work
don't comment that though if u are using api route
And auth()->guard('api')->attempt
should work
@shirshak55 thanks sir! it's worked! I don't know why, I already do dump-autoload before but still doesn't work, but it's work this time! Thanks! :)
why would u use jwt for horizon it should work perfectly on session based auth
On Tue, Oct 15, 2019, 3:57 PM François M. notifications@github.com wrote:
Anyone got authentication to work with Laravel Horizon?
// config/horizon.php 'middleware' => ['web', 'jwt.auth'],
// HorizonServiceProvider.php Gate::define('viewHorizon', function ($user) { return in_array($user->email, [ 'email@example.com', ]); });
I tried getting the user in boot, but auth()->guard()->user() always returns null.
Thanks.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/tymondesigns/jwt-auth/issues/1669?email_source=notifications&email_token=AB5Y4YPEKZGZICW7VJEMNE3QOWJSFA5CNFSM4FWRKMQ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBIGYEY#issuecomment-542141459, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB5Y4YIJKV5QWIQZVEWQHADQOWJSFANCNFSM4FWRKMQQ .
@shirshak55 I'm still having issues even if I'm using the same as what example you have given. I'm getting error in my postman saying
Method Illuminate\Auth\SessionGuard::factory does not exist.
My bad. I just missed to modify this part also
'expires_in' => $this->guard()->factory()->getTTL() * 60 //used auth() instead of the example above
@shirshak55 Can you please explain to me sir, why both my login and register function works if excluded on middleware('auth:api')?
@fingersandmind sir are u using web.php file or api.php file inside routes? By default api uses api middleware and web uses web middleware . So horizon etc can only work on web middle as per as I know.
Regarding login u must only use api middleware and do have to configure guards etc properly so it wont collide sir.
For anyone that wants to handle this better...
I used the following.
https://medium.com/@JinoAntony/multi-user-api-authentication-using-laravel-jwt-8ae572b0c4cf
It does a better job of this by creating a middleware that assigns a guard
This way you dont have to change your Auth config only add a provider and then use the assign guard middleware on the route to selectively assign the guard you want to use.
Do note the jwt.auth will fail a route that is not authenticated so only use the guard like so
Route::group(['middleware' => ['assign.guard:users']],function () {});
if you have a route that is authenticate with a token you can add on that jwt.auth.
This resolves the issue of needing to add the api as default allowing you to use the web frontend and api without issue.
This solved it for me.. https://laracasts.com/discuss/channels/laravel/jwt-auth-and-laravel-basic-auth-problem
Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
i have a website and i want to do security with jwt how can i do this with web.php without using api
Hi there,
until now i use jwt to login in my api. But now i want to use Horizon additionally. To secure the horizon app, i want to use the laravel LoginController. The Login succes, but the auth()->user() is everytime null. Mayby its an conflict with JWT, what can i do?
Cheers Ralf