I have a Laravel 8 project. I want to change magic auth error message. And I did updated my code like this.
'This code has already been used' I replaced this message with this in the context of the code 'You will get a link in your email inbox every time you need to log in or register. Keep in mind that each link can only be used once.'
OLD AuthController.php
public function magicauth(Request $request)
{
$auth = app('firebase.auth');
$email = $request->email;
$oobCode = $request->oobCode;
$exits = User::where('email', $email)->first();
if(!is_null($exits))
{
if(is_null($exits->firebaseUserId))
{
$fUser = $auth->createUser([
'email' => $exits->email,
'emailVerified' => true,
'displayName' => $exits->name,
'password' => ($exits->email . $exits->id),
]);
$firebaseID = $fUser->uid;
$exits->update([
'firebaseUserId' => $firebaseID
]);
}
}
try
{
$result = $auth->signInWithEmailAndOobCode($email, $oobCode);
$firebaseID = $result->firebaseUserId();
$user = User::where('firebaseUserId', $firebaseID)->first();
if(is_null($user))
{
return view('auth.messages', ['message' => 'User not found']);
}
if($user->role_id != 3)
{
return view('auth.messages', ['message' => 'User is not creator']);
}
Auth::login($user);
return redirect()->route('home');
} catch (\Exception $e) {
return view('auth.messages', ['message' => 'This code has already been used.']);
}
return redirect()->route('login');
}
NEW AuthController.php
public function magicauth(Request $request)
{
$auth = app('firebase.auth');
$email = $request->email;
$oobCode = $request->oobCode;
$exits = User::where('email', $email)->first();
if(!is_null($exits))
{
if(is_null($exits->firebaseUserId))
{
$fUser = $auth->createUser([
'email' => $exits->email,
'emailVerified' => true,
'displayName' => $exits->name,
'password' => ($exits->email . $exits->id),
]);
$firebaseID = $fUser->uid;
$exits->update([
'firebaseUserId' => $firebaseID
]);
}
}
try
{
$result = $auth->signInWithEmailAndOobCode($email, $oobCode);
$firebaseID = $result->firebaseUserId();
$user = User::where('firebaseUserId', $firebaseID)->first();
if(is_null($user))
{
return view('auth.messages', ['message' => 'User not found']);
}
if($user->role_id != 3)
{
return view('auth.messages', ['message' => 'User is not creator']);
}
Auth::login($user);
return redirect()->route('home');
} catch (\Exception $e) {
return view('auth.messages', ['message' => 'You will get a link in your email inbox every time you need to log in or register. Keep in mind that each link can only be used once.']);
}
return redirect()->route('login');
}
But when I try now, I see that the message has not changed. How can I fix this?
Please follow below steps:
If you haven't done it yet, delete or rename the old AuthController class, use only new one, with new message.
Make sure routes going to the methods in the new controller
Run composer dump-autoload.
If the problem still persist I'd check whether some kind of cache mechanism is enabled in php, like opcache.
Related
I created a new project in Laravel that consumes all data from an API. For private data like a user profile, I need an access token to get the data.
Once I have an access token, how do I set the token as Auth::id() in Laravel? Or perhaps I can store the user profile as Auth::user() so that I can use #auth in a frontend blade file?
class CustomAuthController extends Controller
{
public function index()
{
return view('login');
}
public function store(Request $request)
{
$request->validate([
'phone' => 'required|numeric'
]);
$data = [
'phone' => $request->phone
];
$codeSent = GeneralFunction::WebRequestPublicApi('first-login', $data, null, null, null, true);
if($codeSent->status == "success")
{
return redirect('verify');
} else {
$errors = new MessageBag();
$errors->add("phone", "Invalid phone number");
return view('login')->withErrors($errors);
}
}
public function showVerify()
{
return view('verify');
}
public function verify(Request $request)
{
try {
$request->validate([
'verify' => 'required|size:6'
]);
$data = [
'token_code' => $request->verify,
'source' => 'web'
];
$token = GeneralFunction::WebRequestPublicApi('verify-login', $data, null, null, null, true);
if($token->status === "success")
{
$userData = GeneralFunction::WebRequestPublicApi('membership', null, 'GET', null, null, true, $token->results->access_token);
if($userData->status !== "error")
{
$user = (array) $userData->results[0];
$request->session()->put('token', $token->results->access_token);
Auth::attempt($user, false, false);
return redirect('/');
}
} else {
$errors = new MessageBag();
$errors->add("verify", "Invalid Token");
return view('verify')->withErrors($errors);
}
} catch (Exception $e) {
$errors = new MessageBag();
$errors->add("verify", $e->getMessage());
return view('verify')->withErrors($errors);
}
}
}
I tried using Auth::attempt, Auth::login(), and the other method, but all of these required a user table. My project does not have a database.
You can do something like following.
In the controller
if($auth_ok)
{
session(['user' => ['key' => 'value', 'key2' => 'value2'] ]); // set session data
return view('frontend');
}
In the view
$user = session('user', false);
#if(!$user) // if not logged in
do something
#else // logged in successfully
Welcome my user
#endif
Hope this helps.
i guess the best thing you need to do is to use sqlite and once you got login from your api create a new user from it or find if there is existing already and Auth::login($newUser);
I am using jwt-auth for my Laravel 5.7 app. Currently, I'm allowing the client to enter email and password as user credentials.
However, I also want to let the client to enter their username in place of their email. So they have 2 choices: email or username.
How can I do that in my code?
My UserController#authenticate
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
try {
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json([
'status' => 401,
'message' => 'invalid_credentials',
], 401);
}
} catch(JWTException $e) {
return response()->json([
'status' => 500,
'message' => 'token_creation_failed',
], 500);
}
return response()->json(compact('token'));
}
Thanks in advance
In your AuthController, add this to the login method;
public function login()
{
$loginField = request()->input('login');
$credentials = null;
if ($loginField !== null) {
$loginType = filter_var($loginField, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
request()->merge([ $loginType => $loginField ]);
$credentials = request([ $loginType, 'password' ]);
} else {
return $this->response->errorBadRequest('What do you think you\'re doing?');
}
if (! $token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
This is how I handled mine where user can choose either email or phone to login.
public function login(Request $request)
{
//validate incoming request
$this->validate($request, [
'email_phone' => 'required|string',
'password' => 'required|string',
]);
try {
$login_type = filter_var( $request->email_phone, FILTER_VALIDATE_EMAIL ) ? 'email' : 'phone';
// return $login_type;
$credentials = [$login_type => $request->email_phone, 'password'=>$request->password];
if (! $token = Auth::attempt($credentials)) {
return response()->json($this->customResponse("failed", "Unauthorized"), 401);
}
return $this->respondWithToken($token);
} catch(JWTException $e) {
return response()->json($this->customResponse("failed", "An error occured, please contact support.", $user), 500);
}
}
Ok so what i'm trying todo, do not let login if user has not confirmed his account by email. My login code looks like that:
public function postLogin()
{
$credentials = [
'confirmed' => 0,
'email' => Input::get('email'),
'password' => Input::get('password')
];
$user = Sentinel::authenticate($credentials, false); // Login the user (if possible)
if ($user and $user->banned) {
Sentinel::logout();
$user = null;
}
if ($user) {
return $this->afterLoginActions();
} else {
$this->alertFlash(trans('app.access_denied'));
return Redirect::to('auth/login');
}
}
But i can still login without any errors. Any help? Thanks guys!
Edited: working, but now i dont get flash message if my details are incorect.
Code:
public function postLogin()
{
$credentials = [
'email' => Input::get('email'),
'password' => Input::get('password'),
'confirmed' => 1
];
$user = Sentinel::authenticate($credentials, false); // Login the user (if possible)
if ($user and $user->banned) {
Sentinel::logout();
$this->alertFlash(trans('app.banned'));
$user = null;
}
if ($user->confirmed==1) {
return $this->afterLoginActions();
}
else if ($user->confirmed==0) {
Sentinel::logout();
$this->alertFlash(trans('app.not_active'));
return Redirect::to('auth/login');
} else {
$this->alertFlash(trans('app.access_denied'));
return Redirect::to('auth/login');
}
}
Do you have a column in your table storing the information if this user passed the email confirmation? If you have one, this is what I do it with typical Laravel postLogin method.
public function postLogin(Request $request)
{
$credentialas = (your credential here);
// only check credentials
if ($this->guard()->once($credentials)) {
$currentStatus = $this->guard()->user()->status;
if (intval($currentStatus) === (NOT_CONFIRMED)) {
$this->guard()->logout();
return $this->sendSuspendedResponse($request);
} else {
$this->guard()->login($this->guard()->user());
return $this->sendLoginResponse($request);
}
}
}
Is it possible when user type his login username and password to store his details and redirect him to another page where I will query database for addition information which he provide before to log him? Consider this scenario:
User enter username/password
If they are correct store this user information and redirect to another page ( not logged yet )
Query database for addition information about this user
This is what I have so far
public function login() {
return View::make('site.users.login');
}
public function loginSubmit() {
$validatorRules = array(
'username' => 'required|alpha_dash',
'password' => 'required|min:6'
);
Input::merge(array_map('trim', Input::all()));
$validator = Validator::make(Input::all(), $validatorRules);
if ($validator->fails()) {
return Redirect::to('/users/login')->withErrors($validator->errors())->withInput(Input::except(['captcha']));
}
$user = User::where('username', Input::get('username'))->first();
if (!$user) {
$validator->messages()->add('username', 'Invalid login or password.');
return Redirect::to('/users/login')->withErrors($validator->errors())->withInput(Input::except(['captcha']));
}
if (!Hash::check(Input::get('password'), $user->password)) {
$validator->messages()->add('username', 'Invalid login or password.');
return Redirect::to('/users/login')->withErrors($validator->errors())->withInput(Input::except(['captcha']));
}
Session::put('user', ['user_id' => $user->user_id]);
return Redirect::to('/users/auth/' . $user->user_id . '?_token=' . csrf_token())->with('message_success', '.');
}
public function loginAuth() {
Session::get('user', ['user_id' => $user->user_id]);
$key = DB::table('users')->select('key')->where('user_id', '=', $data->user_id)->first();
return View::make('site.users.auth', [
'key' => $key
]);
}
Or there is another way to do this? This portion of source gave simple error
production.ERROR: exception 'ErrorException' with message 'Undefined variable: user'
On session get function
Session::get('user', ['user_id' => $user->user_id]);
You can fix your code like this:
public function loginAuth()
{
$data = Session::get('user');
$key = DB::table('users')->select('key')->where('user_id', '=', $data->user_id)->first();
return View::make('site.users.auth', [
'key' => $key
]);
}
This is pretty standard login function and validation that works nicely. But I also want to check that the user is active. I have set up a column in my users table with 'active' set to either 0 or 1.
public function post_login()
{
$input = Input::all();
$rules = array(
'email' => 'required|email',
'password' => 'required',
);
$validation = Validator::make($input, $rules);
if ($validation->fails())
{
return Redirect::to_route('login_user')
->with_errors($validation->errors)->with_input();
}
$credentials = array(
'username' => $input['email'],
'password' => $input['password'],
);
if (Auth::attempt($credentials))
{
// Set remember me cookie if the user checks the box
$remember = Input::get('remember');
if ( !empty($remember) )
{
Auth::login(Auth::user()->id, true);
}
return Redirect::home();
} else {
return Redirect::to_route('login_user')
->with('login_errors', true);
}
}
I've tried something like this already:
$is_active = Auth::user()->active;
if (!$is_active == 1)
{
echo "Account not activated";
}
But this can only be used within the 'auth attempt' if statement and at that point the users credentials(email and pass) are already validated. So even if the users account if not active at this point they are already logged in.
I need a way to return validation to let them know they still need to activate their account and check if their account is set at the same time their email and pass are being checked.
Filters are the way to go. It's easy and clean to solve this problem, see my example below.
Route::filter('auth', function()
{
if (Auth::guest())
{
if (Request::ajax())
{
return Response::make('Unauthorized', 401);
}
else
{
return Redirect::guest('login');
}
}
else
{
// If the user is not active any more, immidiately log out.
if(Auth::check() && !Auth::user()->active)
{
Auth::logout();
return Redirect::to('/');
}
}
});
Can't you use something like this:
if (Auth::once($credentials))
{
if(!Auth::user()->active) {
Auth::logout();
echo "Account not activated";
}
}
Just make the active field one of the confirmations. You can do this:
$credentials = array(
'username' => $input['email'],
'password' => $input['password'],
'active' => 1
);
if (Auth::attempt($credentials))
{
// User is active and password was correct
}
If you want to specifically tell the user they are not active - you can follow it up with this:
if (Auth::validate(['username' => $input['email'], 'password' => $input['password'], 'active' => 0]))
{
return echo ('you are not active');
}
A better solution might be to create an Auth driver that extends the Eloquent Auth driver already in use and then override the attempt method.
Then change your auth config to use your driver.
Something like:
<?php
class Myauth extends Laravel\Auth\Drivers\Eloquent {
/**
* Attempt to log a user into the application.
*
* #param array $arguments
* #return void
*/
public function attempt($arguments = array())
{
$user = $this->model()->where(function($query) use($arguments)
{
$username = Config::get('auth.username');
$query->where($username, '=', $arguments['username']);
foreach(array_except($arguments, array('username', 'password', 'remember')) as $column => $val)
{
$query->where($column, '=', $val);
}
})->first();
// If the credentials match what is in the database we will just
// log the user into the application and remember them if asked.
$password = $arguments['password'];
$password_field = Config::get('auth.password', 'password');
if ( ! is_null($user) and Hash::check($password, $user->{$password_field}))
{
if ($user->active){
return $this->login($user->get_key(), array_get($arguments, 'remember'));
} else {
Session::flash('authentication', array('message' => 'You must activate your account before you can log in'));
}
}
return false;
}
}
?>
In your login screen, check for Session::get('authentication') and handle accordingly.
Alternatively, allow them to log in but don't let them access any pages other than one that offers a link to resend the activation email.
This is what I do:
if (\Auth::attempt(['EmailWork' => $credentials['EmailWork'], 'password' => $credentials['Password']], $request->has('remember'))) {
if (\Auth::once(['EmailWork' => $credentials['EmailWork'], 'password' => $credentials['Password']])) {
if (!\Auth::user()->FlagActive == 'Active') {
\Auth::logout();
return redirect($this->loginPath())
->withInput($request->only('EmailWork', 'RememberToken'))
->withErrors([
'Active' => 'You are not activated!',
]);
}
}
return redirect('/');
}
return redirect($this->loginPath())
->withInput($request->only('EmailWork', 'RememberToken'))
->withErrors([
'EmailWork' => $this->getFailedLoginMessage(),
]);