How can I log what is going wrong in my controller - php

I am trying to register a user on my website with the laravel/vue.js/vuex. In my store actions, I'm calling the tryRegister action to post a request. But it keeps responding with a 401 error not authorizaed, and I don't understand why. So I made my controller as basic as it can get to just get a response and even then it keeps throwing the 401 authorization error. I'm new to back-end developing and just can't understand why this happens. I do know for sure that the route is working. How can I make my controller function give a basic response to see if it is working? And why is it giving an authorization error even tho I'm not doing anything with authorization, is that just the standard error a controller gives?
Try register action
tryRegister(context, credentials) {
return new Promise((resolve, reject) => {
axios
.post("/api/auth/register", credentials)
.then(response => {
console.log(response.data);
//context.commit("registerSucces", response.data);
resolve(response.data);
})
.catch(error => {
console.log(error.response);
reject(error);
});
});
}
Authorization controller register function
public function register(Request $request)
{
// $user = User::create([
// 'email' => $request->email,
// 'password' => $request->password,
// ]);
//$token = auth('api')->login($user);
//return $this->respondWithToken($token);
return response()->json(['message' => 'controller register']);
}

your register method of the controller is not accessible because of the auth middleware. so you are getting not authorized error. make it accessible without authorization. in the constructor method of the controller change this line like below.
$this->middleware('auth:api', ['except' => ['login', 'register']]);
login and register are controller's method which will be now accessible without authorization.

Related

Using Laravel and Ajax and a custom package controller, how to login and redirect a user with ajax

I have a pretty base Laravel 9 install.
I wrote a custom package that is installed that provides a route and a controller action. The controller action is designed to Login a user via ajax, and return a response that tells the front end where to redirect the now logged-in user.
/**
* CustomLogin
*
* #param Request $request
* #return string A json response with either success or fail
*/
public function customLogin(Request $request){
// Do some other things to make sure this is ok
$user = User::firstOrCreate([
'something_cool' => $request->address
]);
Auth::login($user);
return response()
->json([
'success' => true,
'message' => 'Successfully Login',
'url' => route('dashboard')
], 200);
}
This all works, I have tested it by logging that the Auth::login($user) works. The response works as well. But then in my JS:
axios.post('/custom-login', {
address: address,
proof: response.proof,
signedMessage: response.signedMessage
})
.then(function (response) {
console.log(response.data);
window.location.href = response.data.url;
})
.catch(function (error) {
console.log(error);
//this.errorHandle('fail', 'Something went wrong.')
});
The response.data.url is just a simple route to the default Laravel dashboard.
There is also a session file created in storage\framework\sessions.
My /dashboard route is:
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware('auth')->name('dashboard');
I did test this as just a controller action in App\Http\Controllers and it worked fine. But somehow in the custom package, the login works and then the redirect to the /dashboard returns a HTTP 302.
How can I log a user in from a custom package controller and have it stick?

How get access token after autorization laravel sanctum?

Hello i'm newbie in laravel. I use for authorization sanctum. But i want that some request can available for authorization user (i use laravel for only api, on front i use angular 2).
web.php:
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::post('api/user-information', function(Request $request) {
return response()->json([ auth()->user()]);
});
// API route for logout user
Route::post('api/logout', [AuthController::class, 'logout']);
});
How can I get access token after success autorization user that i can send request for middleware routes. Because if i have request withous access token i always send null in 'api/user-information'. Please help me resolve this problem.
You could better make a new function in a controller, probably the AuthController. In this function you can validate fields
$validatedData = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
With the validated data you can use Auth::login($validatedData);
Source: https://laravel.com/docs/9.x/authentication#login-throttling
Welcome to Laravel! I am assuming you have login method that authenticates user. You can create a token in that method and pass it to your frontend.
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (! $user || ! Hash::check($request->password, $user->password)) {
return ['status'=>0,'message'=>'Invalid Credentials','data'=>[]];
}
$data = [
'user'=>$user,
'token'=>$user->createToken('MyToken')->plainTextToken
];
return ['status'=>1, 'message'=>'Login Successful!', 'data'=>$data];
}
If you just need to pass the token, you can simply return token in the response and then pass it in request header (Authorization) of your Angular applcation to access the API routes protected by Sanctum middleware auth:sanctum
return $user->createToken('MyToken')->plainTextToken;
Also since you are going to use Laravel for API, I would suggest you put all your routes in routes/api.php file.
The routes in routes/api.php are stateless and are assigned the api middleware group. The prefix '/api' is applied to all the routes defined in api.php
You can read more about it in Laravel Documentation
Issuing API Tokens
The Default Route Files

Laravel 5.5/Angular JWT logout

I have an issue with logging out using JWT package. On Angular side I am removing the token from local storage and calling Laravel API:
logout(): void {
this.cacheHandler.clearCache();
return this.http.get(environment.apiUrl + 'logout')
.toPromise()
.then(response => {
const responseData = response.json();
return responseData.success;
})
.catch(error => {
return error;
});
}
And on Laravel side:
public function logout()
{
try {
JWTAuth::invalidate(JWTAuth::getToken());
return response()->json(['success' => true, 'message' => 'Logout successful'], 200);
} catch (JWTException $e) {
return response()->json(['success' => false, 'error' => 'Failed to logout, please try again.'], 500);
}
}
API method is protected with JWT auth middleware, so when calling API I am forwarding Authorization Bearer token which was stored in local storage. Method passes, token is valid.
After that it enters the logout() method and I am getting the response that logout was successful.
Problem is that I can trigger the same request, with same token, always getting the same message. If it was invalidated, it couldn't trigger the second request because it is behind a middleware.
Also, with the same token, which was supposed to be invalidated, I can call other API methods which require authentication (without the token they don't work)
try using the new JWTGuard and call it like this:
public function logout()
{
$this->guard()->logout(); // pass true to blacklist forever
}
That logout functions calls the following code:
public function logout($forceForever = false)
{
$this->requireToken()->invalidate($forceForever);
$this->user = null;
$this->jwt->unsetToken();
}

Laravel maintain a session through ajax login

How am I able to maintain or create a session through Ajax login. I have a Laravel installation not that much different from a basic make:auth installation.
I had to ovewrite some parts of the authcontroller to return json instead of redirects. Here's the login part:
/**
* Handle an authentication attempt.
*
* #return Response
*/
public function login(Request $request)
{
$this->validate($request, [
$this->loginUsername() => 'required',
'password' => 'required'
]);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
$throttles = $this->isUsingThrottlesLoginsTrait();
if ($throttles && $this->hasTooManyLoginAttempts($request)) {
// to many attempts
if ( $request->ajax() )
{
$this->response['code'] = 406;
$this->response['message'] = $this->sendLockoutResponse($request);
return response()->json($this->response);
}
return $this->sendLockoutResponse($request);
}
$credentials = $this->getCredentials($request);
$credentials['is_active'] = 1;
if (Auth::attempt($credentials, $request->has('remember'))) {
// succes
return $this->handleUserWasAuthenticated($request, $throttles);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
if ($throttles) {
$this->incrementLoginAttempts($request);
}
// error
if ( $request->ajax() )
{
$this->response['code'] = 406;
$this->response['message'] = $this->getFailedLoginMessage();
return response()->json($this->response);
}
return redirect()->back()
->withInput($request->only($this->loginUsername(), 'remember'))
->withErrors([
$this->loginUsername() => $this->getFailedLoginMessage()
]);
}
/**
* Handle an authenticated response.
*
* #return Response
*/
public function authenticated($request, $user)
{
if ( $request->ajax() )
{
$this->response['message'] = "success";
return response()->json($this->response);
}
else
{
return redirect()->intended($this->redirectPath());
}
}
Here are the routes used:
Route::group(['namespace' => 'Auth'], function() {
Route::post('/login', ['uses' => 'AuthController#login', 'as' => 'login']);
Route::post('/registreer', ['uses' => 'AuthController#postRegister', 'as' => 'register']);
Route::post('/reset', ['uses' => 'PasswordController#sendResetLinkEmail', 'as' => 'reset']);
});
I am working with Vue.js in the frontend which get the error and succes responses perfectly. Only after refreshing the browser i am not in a logged in state. How am I able to do this.
There's no session when you are working with AJAX / JSON REST APIs. Instead of sessions, REST APIs use tokens / some kind of authentication.
If you are building a REST API and using VueJS as the front end framework for a single page application, use the api middleware instead of the default web middleware.
Read more information about JSON Web Tokens here:
https://jwt.io/introduction/
You are basically creating a stateless application when you are using Ajax. The frontend side basically didnt need to know the state of the user, wether he is already login or not. So you didnt need any session.
What you need to do is get information from the server wether your user is authorized to get any resource on the server. This is basically Authenticating (the process to validate user credential that being sent to the server and then returning sort of id to the user) and Authorization the process to check wether the id is authorized to access the resource requested.
I guess i declared my question not properly because of the misunderstandings. However i did get it to work. The fix is to put middleware around the specific routes. Now I am to login trough a Ajax request.
Route::group(['middleware' => 'web'], function () {
...
});

User Auth not persisting within Laravel package

This is my first attempt at a laravel package and have run into an issue where Auth::attempt($credentials) works within my login controller, but upon redirection to a protected route or controller, the user is no longer authenticated. Below is my login controller method with the redirect to dashboard commented out.
public function attempt(Request $request){
$email = strtolower(strip_tags(htmlspecialchars($request->input('email'))));
$password = strip_tags(htmlspecialchars($request->input('password')));
if (Auth::attempt(array('email' => $email, 'password' => $password)))
{
// Redirect to dashboard route
//return redirect()->intended('/admin');
if(Auth::check())
print_r(Auth::user());
}
}
A response to valid credentials prints out the correct user record and Auth::check returns true. But, when redirected to the admin controller, the user is not authenticated. Below is the admin controller method that should output the authenticated user, but only returns "not logged".
public function index()
{
if(Auth::check()) print_r(Auth::user());
else echo "not logged";
}
Both controllers use Auth;, their namespaces are consistent with vendor/package/pathToDir, db is setup correctly, and the encryption key has been set. Any ideas on what's going wrong? Thanks
Turns out the issue was with the new web middleware, moved all my routes that require session data in to the route group and everything works as normal.
Route::group(['middleware' => ['web']], function () {
Route::get("/login", ['uses'=>'SiteLogin#index']);
Route::post("/login", ['uses'=>'SiteLogin#attempt']);
Route::get("/logout", ['uses'=>'SiteLogin#logout']);
Route::group(['prefix' => 'admin', 'middleware' => 'auth'], function () {
Route::get('/', ['uses'=>'Admin#index']);
});
});
The default behavior of the method attempt is to not keep the user logged.
You should change it to:
if (Auth::attempt(array('email' => $email, 'password' => $password), false, true))
This way you will set remember as false and login as true.
Check more about this here: https://laravel.com/docs/5.2/authentication

Categories