Laravel JWT ATUH can't maintain user to other page - laravel

AS see my captures,
i made jwt login page.
it makes jwt token but after that,
go home and check user's name but Auth::user() is null
if i dd($user) on api/auth/login page, user's info appears
but go home page and trying to check user's info, there is only null page
here is my full code.
https://github.com/sksmsWKd/MetaComposerProto
would you do me a favor?
this is my login function on AuthController.
it makes jwt token well but can't maintain user's login to other page...
$input = $request->only('email', 'password');
$jwt_token = null;
if (!$jwt_token = JWTAuth::attempt($input)) {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], Response::HTTP_UNAUTHORIZED);
}
return response()->json([
'success' => true,
'token' => $jwt_token,
]);

Related

How to test Auth::once() in Laravel?

I'm using Auth:once() to authenticate users for a single request.
if (!Auth::once($this->only('email', 'password'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'email' => __('auth.failed'),
]);
}
// we store the user + password for one request in the session
// so we can use it in the next request
$this->session()->put('email', $this->email);
$this->session()->put('password', $this->password);
But the test user is permanently authenticated, and assertGuest() is always false, not just for a single request. This is happening only in the test!
$user = User::factory()->create();
$response = $this->post('/api/login', [
'email' => $user->email,
'password' =>' password',
]);
$response = $this->get('/api/home');
$this->assertGuest();
I tested manually from Postman, and everything seems to be okay. So I think Laravel considers it a single request for the entire test.

Laravel 8 reset password in PWA

I am trying to establish a password reset system in a Laravel + SPA environment with Vuejs. Except for the form that starts the process ('I have forgotten my password'), the rest of the actions I want to be carried out in the standard Laravel way, outside the spa and using Laravel Auth. So I have:
web.php
//This sends a custom email notification.
Route::post('/forgot-password', 'UserController#reestablecerPassword')->middleware('guest')->name('password.email');
//Shows the standard view auth.passwords.reset, when we can reset password values.
Route::get('/reset-password/{token}', function ($token) {
return view('auth.passwords.reset', ['token' => $token]);
})->middleware('guest')->name('password.reset');
//Route to custom method in order to receive and process the previous form
Route::post('/reset-password', 'UserController#procesarReestablecerPassword')->middleware('guest')->name('password.update');
//this returns a simple view where it is reported that the password has been changed
Route::get('/changedpassword', function () {
return view('changedpassword');
})->name('changedpassword');
Methods in UserController.php
//Handles the response by email and the response to the front-end to inform that the email has been sent
public function reestablecerPassword(Request $request){
$request->validate(['email' => 'required|email']);
$status = Password::sendResetLink(
$request->only('email')
);
Log::info('status:');
Log::info($status);
$status == 'passwords.sent' ? $respuesta = response('OK', 200) : $respuesta = response('KO', 400);
return $respuesta;
}
//Process the request that contains the form data and reset the password. The program flow does not execute this method in production, the log is not written
public function procesarReestablecerPassword(Request $request) {
Log::info('entra a procesarReestablecerPassword con estos valores en la petición:');
Log::info($request);
$request->validate([
'token' => 'required',
'email' => 'required|email',
'password' => 'required|min:8|confirmed',
]);
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function ($user, $password) use ($request) {
$user->forceFill([
'password' => Hash::make($password)
])->save();
$user->setRememberToken(Str::random(60));
event(new PasswordReset($user));
}
);
return $status == Password::PASSWORD_RESET
? redirect()->route('changedpassword')->with('status', __($status))
: back()->withErrors(['email' => [__($status)]]);
}
The issue appears when we submit the reset-password view form, when I get the error:
The GET method is not supported for this route. Supported methods: POST.
Observing the operation in the web browser:
In the local environment, where the operation is correct, two actions happen after pressing the submit button of the form:
A first POST type is sent with the form data. Such as:
https://appname.com/reset-password
A 'Location' header is received to redirect to a second URL via GET that includes the user token. Being of type:
https://appname.com/reset-password/jkladjfñl9iu08adDjfjnnakRfpaiw
Well, in the production environment, this token is not found in the url received in the Location header (I don't know why this occurs)
Thanks in advance.

Why Auth::check() returns true after logout ? Passport

So I made Authentication using passport, everything worked fine until I logged user out. My paths are protected via auth:api guard so after logging out I can't access any functions, however my frontend is rendered via react based on Auth:check() value and it stays true after logging out. Therefore I am able to get into admin dashboard without any permissions, which is a bug and I can't find a solution to fix it.
This is my log out function:
public function logout()
{
if (Auth::check()) {
DB::table('oauth_access_tokens')
->where('user_id', Auth::user()->id)
->update([
'revoked' => true
]);
return response(['check' => Auth::check()]); // I get true after logging out
}
return response(['check' => Auth::check()]);
}
This is my login and register functions:
public function register(Request $request){
$validatedData = $request->validate([
'name' => 'required|max:55|unique:users',
'password' => 'required'
]);
$validatedData['password'] = bcrypt($request->password);
$user = User::create($validatedData);
$accessToken = $user->createToken('authToken')->accessToken;
return response()
}
public function login(Request $request)
{
$loginData = $request->validate([
'name' => 'required',
'password' => 'required'
]);
$a = auth()->attempt($loginData, true);
if(!$a) {
return response(['message'=>'Invalid credentials');
}
$accessToken = auth()->user()->createToken('authToken')->accessToken;
return response()->json($accessToken);
}
What have I missed?
The reason that Auth::check() returns true is the user is set on the auth service. You are only revoking the access token, meaning that the user will be logged out from the next request.
You can solve this one of two ways
1) Assume that the any call to the logout route will result in the user being logged out, irrespective of the logic performed. For example, you could make the call and then clear the access token in your frontend (or perform whatever other logout logic).
2) You can call Auth::logout() in your code, which will set the current user on the authentication service to null resulting in Auth::check() returning false.

Lumen Custom Authentication with custom Fields and Store in Auth Guard

I am using lumen for API development. I have an issue in Lumen Custom Authentication.
I want to login a user when his credentials and account_name matches with stored record. In the credentials filed there is not username and password type data.
here my login method
public function login(Request $request)
{
$this->validate($request,[
'data.credentials' => 'required',
'data.account_name' => 'required',
]);
try {
$credentials=$request->data['credentials'];
$account_name=$request->data['account_name'];
$user=User::where('account_name',$account_name)->where('credentials',$credentials)->first();
if($user){
// storing the authenticated user to the guard session
$auth_token=Hash::make($account_name . ":" . $credentials);
// update user auth token
$user->auth_token=$auth_token;
$user->update();
$data="Some Data";
return response()->json([
"auth_token"=> $auth_token,
"data"=>$data,
"request_id"=> uniqid(),
"status"=> "success"
]);
}
} catch (\Exception $e) {
return response()->json(array(
'error' => $e->getMessage(),
'status' => 'failed',
'status_code' => 500
));
}
}
I authenticated user with credentials I want to store that user in guard that can be default guard or custom and want to return auth_token from every response. if I use following code it give me an error.
Auth::guard()->attempt(['credentials'=>$credentials,'account_name'=>$account_name]);
It give an error that attempt_undefined_method. and If I use the following code
Auth::guard()->check(['credentials'=>$credentials,'account_name'=>$account]);
it returns the false value and do not store user in guard. I want such type of response from every request where I applied auth middleware
return response()->json([
"auth_token"=> auth()->user()->auth_token,
"data"=>$data,
"request_id"=> uniqid(),
"status"=> "success
]);
following is my AuthMiddleware.php code
$header=$request->header('Auth-Token');
if(Auth::guard('api')){
// we can use $user variable for further :)
return $next($request);
}

Laravel - Oauth password grant

I find it difficult to wrap my head around the password grant authentication process.
What I'm trying to achieve: A mobile device sends the username and the password of a registered user to the API and gets the access token as a response in JSON form.
What I've achieved so far: The API receives the user credentials (username and password) and authenticates the user using Laravel's built-in Auth authentication system.
I know that at this point I should proceed to Oauth authentication. Once the credentials pass the Auth step, I have the user's username, password (specified in the users table) and I can get the client_id and client_secret from the oauth_clients table, but I'm not sure how to accomplish the rest. Do I need to make another POST request? If yes, then how do I do it from the controller?
I am actually implementing this right now. Let me show you some code.
This is my part of my login function:
// this does the process for getting the access token
$oauth = AuthorizationServer::performAccessTokenFlow();
// some hacks
$oauth = (array) $oauth;
// more hacks
$oauth = json_decode($oauth["\0*\0data"], true);
// checks if a token was actually generated
if(!in_array('bearer', $oauth))
{
// returns what was generated if the token is missing
return Responser::error(400, $oauth);
}
You would have to post additional data on your login other than the username and password of the user.
So your post request will contain:
username=the_username
password=the_password
grant_type=password
client_id=the_client_id
client_secret=the_client_secret
note that grant_type=password is constant.
Now you have to check the configurations of the package too found at app/config/packages/lucadegasperi/oauth2-server-laravel/oauth2.php:
You should have the following code:
'password' => array(
'class' => 'League\OAuth2\Server\Grant\Password',
'access_token_ttl' => 604800,
'callback' => function($username, $password){
$credentials = array(
// change this to username if username is the field on your database
'email' => $username,
'password' => $password,
);
$valid = Auth::validate($credentials);
if (!$valid) {
return false;
}
return Auth::getProvider()->retrieveByCredentials($credentials)->id;
}
),
And you are done.
update
the code above that generates the token is inside this function:
// allow user to login with username or email and password
$user_pass = array('username' => $username, 'password' => $password);
$email_pass = array('email' => $username, 'password' => $password);
// check if input is email and use $email_pass combination or else use $user_pass combination
$login = ($isEmail->passes() ? $email_pass : $user_pass);
// try to authenticate username & password
if (Auth::attempt($login))
{
// now you are authenticated here
// get the client id and secret from the database
// maybe use curl or some hacks
// login stuff and token generation
}
This is a bit of an old post, but if you are looking to do this without having multiple post requests, you could always just do something like:
//Get Oauth creds
$apiCreds = OauthClient::where('email', Input::get('email'))->first();
//Provide additional post data for password grant
Input::merge([
'grant_type' => 'password',
'client_id' => $apiCreds->id,
'client_secret' => $apiCreds->secret,
'username' => Input::get('email'),
'password' => Input::get('password'),
'scope' => 'all'
]);
//Login
return AuthorizationServer::performAccessTokenFlow();

Resources