Tymon JWTAuth for custom model which is not user model - laravel-5

I want to create JWT using client model. All the login credentials are saved in the clients table. Here in my Laravel 5.4 application I dont want to have users model. My piece of code is being showing. Now when I am trying to login laravel querying from users table which I don't. I want it from clients table. All the required namespaces I have added top in my controller file. Need help to get a solution.
\Config::set('jwt.user', 'App\Client');
\Config::set('auth.providers.users.model', \App\Client::class);
$credentials = ["username"=>$user_name,"password"=>$password];
$token = null;
try {
if (!$token = JWTAuth::attempt($credentials)) {
return response()->json([
'response' => 'error',
'message' => 'invalid_email_or_password',
]);
}
} catch (JWTAuthException $e) {
return response()->json([
'response' => 'error',
'message' => 'failed_to_create_token',
]);
}
return response()->json([
'response' => 'success',
'result' => [
'token' => $token,
'message' => 'I am front user',
],
]);

I think you need to change the providers => users => model => to your custom namespace in config/auth.php
Example
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class, <= change this to your custom namespace
],
],

Related

Laravel - Redis error when dispatching a job

On one of the systems that I take care of, some times some jobs don't get dispatched due to a connection problem with Redis and this ends up returning an error to the user, on our side we can ignore this error and just miss this job, I looked for how to deal with it on Google and I didn't find anything about it.
public function sendMessage(Request $request, Model $model)
{
// Do the necessary stuff
ResolveMessageBilling::dispatch($model, $request->all());
return response()->json([
'message' => 'The message was succesfully sent'
], 200);
}
This is the error we are getting: RedisException - socket error on read socket
How to ignore the error if it occurs? A simple try/catch can resolve the issue?
public function sendMessage(Request $request, Model $model)
{
// Do the necessary stuff
try {
ResolveMessageBilling::dispatch($model, $request->all());
} catch(\Exception $e) {}
return response()->json([
'message' => 'The message was succesfully sent'
], 200);
}
If you want to bypass ANY error, you should use \Throwable instead of \Exception
public function sendMessage(Request $request, Model $model)
{
// Do the necessary stuff
try {
ResolveMessageBilling::dispatch($model, $request->all());
} catch(\Throwable $e) {}
return response()->json([
'message' => 'The message was succesfully sent'
], 200);
}
see Error Hierarchy: https://www.php.net/manual/en/language.errors.php7.php
If you want to bypass only the \RedisException, you should be able to use:
public function sendMessage(Request $request, Model $model)
{
// Do the necessary stuff
try {
ResolveMessageBilling::dispatch($model, $request->all());
} catch(\RedisException $e) {}
return response()->json([
'message' => 'The message was succesfully sent'
], 200);
}
If you don't want to setup Redis just want to fixed/remove errors only, follow this article: https://laravel.com/docs/7.x/errors
IF you want to Setup Redis(config -> detabase.php) properly, follow few step like this:
'redis' => [
'client' => 'predis',
// Keep Default as is you want to use both redis and sentinel for different service(cache, queue)'
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
// Create a custom connection to use redis sentinel
'cache_sentinel' => [
// Set the Sentinel Host from Environment (optinal you can hardcode if want to use in prod only)
env('CACHE_REDIS_SENTINEL_1'),
env('CACHE_REDIS_SENTINEL_2'),
env('CACHE_REDIS_SENTINEL_3'),
'options' => [
'replication' => 'sentinel',
'service' => 'cachemaster'),
'parameters' => [
'password' => env('REDIS_PASSWORD', null),
'database' => 0,
],
],
],
],
if you needs to Redis sentinal cache, can create new cache connection to use the above sentinal connection like this:
'stores' = [
//Default config
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
// Custom cache connection(according to you)
'sentinel_redis' => [
'driver' => 'redis',
'connection' => 'cache_sentinel',
],
In laravel app, you can easily use via cache facade:
Cache::store('sentinel_redis')->get('key');
After config Redis properly test again with the clear server cache

Laravel custom table with API token

I am using a custom table customer for login and also Laravel Passport to generate token for my Ionic mobile app. I am stuck at the login code where I need to generate token after query from my custom table.
Below are the login code... I can successfully retrieve the id from database but how to link it with the token?
public function login(Request $request)
{
$phone = $request->input('phone');
$password = $request->input('password');
$user = $token = array();
try {
$rs_login = DB::select("select a.id from customer a where a.active > 0 and a.phone = ? and a.password = ?", [$phone, $password]);
$numrow_login = count($rs_login);
if ($numrow_login != 1) {
$this->error['form-message'] = 'ERR' . __LINE__ . ': Invalid phone number or password';
} else {
$user['id'] = $rs_login[0]->id;
}
} catch (\Illuminate\Database\QueryException $ex) {
$this->error['form-message'] = 'Login service is unavailable';
}
if ($this->error == '') {
$tokenResult = $user['id']->createToken('Personal Access Token'); // How to pass the $user['id'] to generate token?
$token = $tokenResult->token;
$token->save();
$token['access_token'] = $tokenResult->accessToken;
$token['token_type'] = 'Bearer';
$token['expires_at'] = Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString();
}
if ($this->error == '') {
$response['status'] = 'success';
$response['message'] = 'Login successful';
$response['token'] = $token;
} else {
$response['status'] = 'error';
$response['error'] = $this->error;
$response['message'] = (isset($this->error['form-message'])) ? $this->error['form-message'] : 'Please check the form';
}
return response()->json($response);
}
You can just specify a custom table in the config/auth.php instead of rewriting the entire logic
'api' => [
'driver' => 'token',
'provider' => 'customer', // <--- Here
'hash' => false,
],
And create the provider to use the specific table from the database
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'customer' => [
'driver' => 'database',
'table' => 'customer',
],
],
And keep the default login behavior for passport
Hope this helps
// changes to be made in this file: config/auth.php
// Create a custom model to override the User model
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
//custom provider
'customProvider' => [
'driver' => 'eloquent',
'model' => App\CustomModel::class, // put custom model here
],
],
// attach your custom provider within the api guard to use with api calls
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'customProvider', // put custom provider here
],
],
// Use lik this in your api router
Route::group(['middleware' => 'auth:api'], function() {});
// I used it like this in LoginController
$user = CustomModel::where('email', $request -> email) -> first();
if(!Hash::check($request -> password, $user -> password)){
return response()->json(['message' => 'Authentication failed. Please check your
credentials and try again!'], 401);
}
Auth::login($user);
$accessToken = Auth::user() -> createToken('authToken') -> accessToken;

Laravel - How to retrieve the last saved data from the database and display it

I am developing a client portal application using Angular-7 as frontend and Laravel-5.8 as the backend. From the Laravel Query (API) below, anyone that gets to the site can send quote (Registered or not):
public function createClientQuote(Request $request) {
$request->validate([
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email',
'phone' => 'required|max:14',
'commodity' => 'required'
]);
$clientquote = new ClientQuote;
$clientquote->first_name=$request->get('first_name');
$clientquote->last_name=$request->get('last_name');
$clientquote->email=$request->get('email');
$clientquote->phone=$request->get('phone');
$clientquote->commodity=$request->get('commodity');
$clientquote->save();
return response()->json([
'message' => 'Quote Successfully Sent!'
], 201);
}
I want to write another Laravel query (API) that as soon as the one above is saved into the database, the information will be immediately retrieved and displayed to the screen. How do I achieve this?
You can do that with :
return response()->json([
'message' => 'Quote Successfully Sent!',
'Data'=> $clientquote
], 201);
Or :
return response()->json([
'message' => 'Quote Successfully Sent!',
'Data'=> ClientQuote::latest()->first()
], 201);

Laravel Multiple Auth using JWT auth every-time i get wrong password

I have 2 user i.e user and bus and for them i have different model
I am using laravel 5.5 with tymondesigns/jwt-auth 1.0.0-rc.1 verson
user is working perfect for user i am getting token also
but bus user us getting 'invalid_email_or_password'
link to full code full source code link
here is my user model:
class User extends Authenticatable implements JWTSubject{
use Notifiable;
protected $fillable = ['name', 'email', 'password'];
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return [];
}}
my config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
'bus' => [
'driver' => 'session',
'provider' => 'buses',
],
'bus-api' => [
'driver' => 'jwt',
'provider' => 'buses',
],
],
my provider are :
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Admin::class,
],
//next
'buses' => [
'driver' => 'eloquent',
'model' => App\Bus::class,
],
my
my buslogincontroller which is taking user name & password for user table
public function busLogin(Request $request)
{
\Config::set('jwt.user', "App\Bus");
\Config::set('auth.providers.users.model', \App\Bus::class);
$credentials = $request->only('email', 'password');
try {
\Config::set('jwt.user', "App\Bus");
\Config::set('auth.providers.users.model', \App\Bus::class);
if (!$token = JWTAuth::attempt($credentials)) {
\Config::set('jwt.user', "App\Bus");
\Config::set('auth.providers.users.model', \App\Bus::class);
return response()->json([
'response' => 'error',
'message' => 'invalid_email_or_password',
]);
}
} catch (JWTAuthException $e) {
return response()->json([
'response' => 'error',
'message' => 'failed_to_create_token',
]);
}
return response()->json([
'response' => 'success',
'result' => [
'token' => $token,
'message' => 'I am Admin user',
'user' => '99',
],
]);
}
my routes api:
Route::post('bus/auth/login', 'Bus\Auth#busLogin');
Route::post('bus/auth/register', 'Bus\Auth#busRegister');
whenever I try to login with Bus model username & password i get invalid login in buscontroller login route but if i try to login with user model credintials i get token in return
how to setup multiple auth with jwtauth with laravel 5.5
There is no need to change the providers in config/auth.php.
You can change the __construct function in each of your controllers as follows. So that jwt know which model to authenticate.
BusController
function __construct()
{
Config::set('jwt.user', Bus::class);
Config::set('auth.providers', ['users' => [
'driver' => 'eloquent',
'model' => Bus::class,
]]);
}
AdminController
function __construct()
{
Config::set('jwt.user', Admin::class);
Config::set('auth.providers', ['users' => [
'driver' => 'eloquent',
'model' => Admin::class,
]]);
}
You just need to set below code before route call in route api
\Config::set('jwt.user', "App\Bus");
\Config::set('auth.providers.users.model', \App\Bus::class);

Laravel add new email template for resetting password

I have two laravel instances connected to an API. Default "password reset" functionality was created for the #1 website but now, I want to add new email templates for the users which are trying to reset their password from the second website.
public function emailResetLink(CanResetPasswordContract $user, $token, Closure $callback = null)
{
$view = $this->emailView;
return $this->mailer->send($view, compact('token', 'user'), function ($m) use ($user, $token, $callback) {
$m->to($user->getEmailForPasswordReset());
if (! is_null($callback)) {
call_user_func($callback, $m, $user, $token);
}
});
}
$view logs auth.emails.password from auth.php (email template for #1 website)
'passwords' => [
'users' => [
'provider' => 'users',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
I've added a hidden input to differentiate the users but I don't know how to use that in order to send another email template.. Any idea would be much appreciated!

Resources