I'm new to Lumen and building a RESTful API and I got stuck for how many hours now because Auth::attempt is not working. I've been searching for any answers but all the results are only Laravel not Lumen.
So I created a AuthController and login method to authenticate user but I got an error.
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required|string|email',
'password' => 'required|string',
]);
$credentials = $request->only('email', 'password');
if( !Auth::attempt($credentials) ) {
return response()->json([
'message' => 'Unauthorized'
], 401);
}
}
This is the error: "Method Illuminate\Auth\RequestGuard::attempt does not exist."
Anyone can help me? Thank you!
Can you try following:
if (!Auth::guard('web')->attempt($credentials) {
return response()->json([
'message' => 'Unauthorized'
], 401);
}
The method is only available for routes which are using the web middleware, could you check that out?
You may need to edit your config/auth file.
Lumen Passport Setup:
composer require dusterio/lumen-passport
Enable the app and auth service providers in bootstrap/app.php
add the following service providers in the bootstrap file
$app->register(Laravel\Passport\PassportServiceProvider::class);
$app->register(Dusterio\LumenPassport\PassportServiceProvider::class);
replace the contents inside the boot function of the auth service provider in /app/Providers/AuthServiceProvider with:
LumenPassport::routes($this->app->router);
Run php artisan migrate
run php artisan passport:install
Then follow this https://laravel.com/docs/5.8/passport#issuing-access-tokens
remeber the lumen version does not have views or routes for authorising access you have to build them seperatly on your client.
Related
Good evening,
I encounter a problem using Laravel and Sanctum to build an Api for a Mobile application.
I followed the documentation and define a route to get a token :
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
Route::post('/sanctum/token', function (Request $request) {
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}
return $user->createToken($request->device_name)->plainTextToken;
});
Tested it with postman, everything works fine, if I pass the right login and password, I'm able to get my token.
Now the problem I'm facing : I protected a route as the documentation said by using this middleware :
Route::middleware('auth:sanctum')->get(' ....'
If I pass my token in headers, it works, but if I don't, Laravel tries to redirect me to /login route, which I don't want of course because I'm creating a mobile application.
** What I want is to receive a 401 if my token isn't valid. **
I tried to define a new middleware and copy the verification of the 'auth:sanctum' but I can't even find where this is defined, since it is not in the Kernel.php file.
I hope someone could explain me how I could find the code of 'auth:sanctum', so I can understand it and create a middleware with the comportement I need, but any help would be appreciate.
Thanks you in advance.
I just deployed a Laravel 9 Passport based API to Digital Ocean. Everything works fine, but when I try lo log an user or an admin and create a token to be stored and returned, I get 500 server error.
I already ran php artisan passport:keys. Because it wasn´t working, I tried to pass the keys by .env through php artisan vendor:publish --tag=passport-config, but still got the error.
Here is my LoginController:
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (!Auth::attempt($credentials)) {
return response()->json([
'message' => 'Usuario y/o contraseña inválidas'
], 401);
}
// If I comment this line and the accessToken in the json response, and return just the Auth::user(), it works fine
$accessToken = Auth::user()->createToken('my_token')->accessToken;
return response()->json([
'user' => Auth::user(),
'accessToken' => $accessToken
], 200);
}
This is my AuthServiceProvider.php boot method:
public function boot()
{
$this->registerPolicies();
/* Passport::routes(); */
if (!$this->app->routesAreCached()) {
Passport::routes();
}
/**
* Controls the expire time for the access token
*/
Passport::personalAccessTokensExpireIn(now()->addDays(30));
Passport::tokensCan([
'admin' => 'Admin',
'user' => 'User',
]);
}
No errors related are being logged neither in Laravel logs nor in nginx ones.
Thanks for your help.
So I figured out the solution with aynber guess.
I try catched the accesstoken line and set debug to true.
It was missing the Personal Client ID, so I ran php artisan passport:client --personal and it worked.
That happens because the client id is self-generated when you first run artisan passport:install.
But when you are cloning a repo and running a migration and a composer install command, you really never run passport:install, so a new client personal id must be run manually.
I'm trying to use the laravel passport to authenticate users. I followed every step in laravel passport documentation. But it shows error when I access a route that is protected by 'auth:api' middleware. I've searched over the internet but any of the answers are not working so far. Please see the code, and what I've tried so far below.
Tech used
Laravel 6
Laravel Passport
Vue 2
Axios
Tried so far:
Changed Passport::routes(); to Passport::routes(null, ['prefix' => 'api/oauth', 'middleware' => ['auth:api', 'web', 'auth']]); in AuthServiceProvider. Also tried Passport::routes(null, ['prefix' => 'api/oauth');
Tried to run php artisan cache:clear
routes/api.php
Route::middleware('auth:api')->group(function() {
Route::get('user', function() {
return request()->user();
});
Route::get('posts', 'PostController#index')->name('posts');
Route::post('posts/store', 'PostController#store')->name('posts.store');
Route::get('posts/{id}/show')->name('posts.show');
Route::get('users/{id}/show')->name('users.show');
});
Axios
mounted() {
axios.get('/api/posts')
.then(res => this.posts = res.data).catch(error => console.log('Unable to fetch posts.'))
}
Error
Headers:
Please let me know if you need some details that is not indicated on my post yet.
Setup
Run composer require laravel/passport:9 for the installation.
Run php artisan migrate for the tables.
Run php artisan passport:install to generate the encryption keys.
Added Laravel\Passport\HasApiTokens trait in User model.
Added Passport::routes(); in AuthServiceProvider.
Changed guard's api driver to passport in config/auth.php.
Full source code:
Click this link
I think you should review your code with the following steps.
Step 1: User model has to use HasApiTokens
...
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
}
Step 2: Passport::routes method within the boot method of your AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
...
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
}
Step 3: In your config/auth.php configuration file, you should set the driver option of the api authentication guard to passport
'guards' => [
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Step 4 (Optional):
If you want to consume your API from your JavaScript application, you need to manually send an access token to the application and pass it with each request to your application. However, Passport includes a middleware that can handle this for you. All you need to do is add the CreateFreshApiToken middleware to your web middleware group in your app/Http/Kernel.php file:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
! You should ensure that the CreateFreshApiToken middleware is the last middleware listed in your middleware stack.
Edit (2021/10/17):
You should try to add the auth middleware to $middlewareGroups of your Kernel.php
protected $middlewareGroups = [
...
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'auth:api', //Need to add
],
];
Edit (2021/10/25):
I downloaded your code and debug it. When you debug it, you will get the following result:
Header JWT is not valid for JSON structure. There seems to be an incompatibility between the Laravel Passport library and your system. You should check your system version (PHP, Laravel, etc). I will continue to investigate. If you have any new information, please let me know
Edit (2021/11/02):
Update your laravel/framework dependency to ^6.0 in your composer.json file. If installed, update your laravel/passport dependency to ^9.3.2 in your composer.json file.
https://laravel.com/docs/6.x/upgrade#updating-dependencies
According to Laravel 6.x documentation, the version of Laravel Passport is from 9.3.2. Please try this version.
If you are using Api/oauth prefix AND add the auth:api middleware than you need to authenticate via Bearer tokens.
So it may be you have csrf token related issue so try below to disable it.
Passport::ignoreCsrfToken(true);
You should add token bearer into your ajax requests. You can get it after successful login.
// laravel
use Illuminate\Support\Facades\Auth;
use App\Models\User;
public function login()
{
$credentials = request(['email', 'password']);
$user = User::where('email', $credentials['email'])->first();
if (!$user || !$token = Auth::attempt($credentials)) {
return response()->json(['success'=> false, 'error' => 'неверный логин или пароль', 'cr' => $credentials], 422);
}
return $this->respondWithToken($token);
}
// vue login
async function login(email, password) {
try {
const response = await axios.post('/auth/login', {email, password});
const token = response.data.token;
// some func to store token, I am using vuex mutations for this
storeToken(token);
}
catch(error) {
console.error(error);
}
};
// vue regular function
async function changePassword(newPassword) {
// get token from global storage, with vuex it will be like store.state.auth.token
const token = getToken();
await axios.post('/user/changePassword', {newPassword}, headers: { Authorization: `Bearer ${token}`});
}
You've forgotten to run php artisan passport:keys ...so there may be no RSA key-pair available, which is crucial. Clients usually can be added with: php artisan passport:client. And generally speaking, there is no default recipe for debugging Laravel middleware ...there only is xdebug.
I often create a login with Laravel, and it runs smoothly, but I don't understand the actual process run by Laravel php artisan make:auth. and now I want to try creating this login process myself to understand the actual process
I'm trying to make the login process run by myself without Laravel make:auth. create a user table with a password that hashed. when logging in Auth::attempt is always false, why?
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
// Authentication passed...
return redirect()->intended('dashboard');
}
}
This function is in the documentation of Laravel Manually Authenticating Users
if i dd(Auth::attempt($credentials)); always return false, so it can't go to route /home:
and my register controller like this:
public function create()
{
$user = User::create([
'name' => Input::get('name'),
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password')),
]);
return redirect::back();
}
how to deal with this?
i think laravel use json callback and middlware and some handled session and cookie
better use basic auth
and check by step to all work currectly in front to end
and see data send to backend currectly
I have set up the Laravel Passport package for Laravel 5.3 just as described in the official documentation (https://laravel.com/docs/5.3/passport#introduction).
I want the API to be consumed by a mobile application, so I am trying to implement Password Grant Tokens. I have created a password grant client, and the token request process...
$response = $http->post('http://my-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => 'client-id',
'client_secret' => 'client-secret',
'username' => 'my#email.com',
'password' => 'my-password',
'scope' => '',
],
]);
...Just works as expected, returning an access-token and a refresh-token for one of my users.
On the one hand,
php artisan route:list
Lists correct middleware for api/user URI: api,auth:api
And driver for api guard is correctly set to passport in config/auth.php.
Summing up, every step of the installation process has been done (https://laravel.com/docs/5.3/passport#installation).
Defaults contents of api.php:
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:api');
The problem comes when I access to http://my-app.com/api/user, because it seems it is authenticating the request using the 'web' middleware, not the 'api'...
When I access, I am redirected to /login (login form) if the user was not logged in, and to /home if it was...
Any help would be really appreciated.
Thanks in advance.
Solved! Just for the record, the solution:
I was sending the request to http://my-app.com/api/user with HTTP Header wrong. I was sending:
Type: Authorization - Content: Bearer: $accessToken
...and the correct way was:
Type: Authorization - Content: Bearer $accessToken (without colon)
I never thought it could be a typo... Anyway, the error was not easy to detect because the redirection to the login form misleaded me from the beginning. I believe it was such an strange behaviour indeed...
The correct solution is removing redirectTo() from this file Authenticate middleware in app/http/middleware/Authenticate.php