Laravel Dual Auth Mechanism: Database and REST API - php

I have to set up an authentication system on Laravel 5.1.19 that will handle two types of users: CMS admin users and regular end users:
The CMS admin credentials will be mapped in Laravel's database so i
can use the default Laravel auth mechanism (Eloquent model & all)
The regular users will be stored on a different db that won't be
directly accessible. The credential checking for regulars is
implemented via a REST call to a dedicated server that can query that
db.
Admins and regulars will have different login pages. My questions are:
How can I have two auth mechanisms mapped to two separate routes?
Say /login/admin is the login URL for CMS admins. This request should be handled by the default auth.
Say /login/users is the login URL for regulars. This should be handled by a custom auth that will issue REST requests to a different server for credential checking and retrieval of other necessary user info.
How can I implement a custom auth mechanism that doesn't store any info in Laravel's db?
Making REST calls should be easy. My problem is that all auth tutorials assume that the user will be mapped in a db table and my requirements make it impossible to do so. I read a post on laravel.io where somebody said that he tried to save the User object in Session but he didn't get into much detail.
Update: A Preliminary Solution
Following this laravel.io post I managed to create a custom UserProvider class that extends Illuminate\Auth\EloquentUserProvider that is overriding the retrieveById($identifier) method such that it first tries to retrieve the user object from the Session. If nothing's found then it delegates the operation to its parent, EloquentUserProvider:
class CustomUserProvider extends EloquentUserProvider {
public function __construct(HasherContract $hasher, $model)
{
parent::__construct($hasher, $model);
}
public function retrieveById($identifier)
{
$user = getSessionUser($identifier);
if ($user) {
return $user;
} else {
return parent::retrieveById($identifier);
}
}
...
Other than this, I just stored the current user in Session in my LoginController.
The setup of a custom UserProvider is documented in the above-mentioned post.
Hope this helps someone and if you guys have something to add, please do.
Thanks!

Related

Using Laravel Passport to only access own account on a few Routes

My whole application has a lot of api routes that serve my frontend with ajax responses. I use Laravel Passport xsrf token protection to protect my routes and manage authentication. However, we are planning to serve an api that a specific type of user can consume. To go in more detail, here is a (fictional) example of what we want to achieve:
A company can have a lot vacancies.
My api routes are a lot, now I want to give the company owner the ability to get all his vacancies over our sdk and place them on his website. The Problem I am facing: As far as I understand passport correctly, personal access tokens are the thing I need. I don’t want a „log in with my application“ functionality (jet), how do I disable this? I want only the user to access his own informations, not from other users. And I probably want in the future to let the user register for different apis. So that he has multiple access tokens for different routes, but the routes are all together in one api.php routes file. I think I would need to use scopes for this, but how do I safely assign the scopes to the tokens, since this only does a single route?
Can someone help me to understand the concept of passport correctly?
I do not use passport, however it seems this issue could be solved with scopes (not needing to be tied to an access token). If you are struggling with getting the authenticated user, you could follow this post:
Get authenticated user with Laravel Passport and grant password
If you are struggling with how to write your scope, here is what I am thinking
You have a table containing companies called companies
You have a table containing employees called employees
You have a table containing vacancies called vacancies
You have a join table called company_employee
Now you can create a scope on your Vacancy model
class User {
public function companies()
{
return $this->hasMany(App\CompanyEmployee::class)
}
}
class Employee {
}
class Company {
}
class CompanyEmployee {
}
class Vacancy {
public function scopeMine($query)
{
$my_companies = auth()
->user()
->companies()
->select('company_id')
->pluck('company_id')
->get()
->toArray();
return $query->whereIn('company_id', $my_companies);
}
}
Then no matter how you are querying the vacancies (through an API or front end GUI), you can simply add the scope to your query presumably in your controller.
class VacancyController {
public function index()
{
return App\Vacancy::mine()->get();
}
}

Middleware laravel

I am new in laravel and I have one problem with middleware. On official laravel site, I found code for creating controller.
When I creating controller it is recommended to add middleware in constructor or this is only if I need some additional functionalities?
Also, if I include auth middleware, did I get some benefits by default, like security checks or similar or I must to rewrite middleware code first?
class UserController extends Controller {
/**
* Instantiate a new controller instance.
*
* #return void
*/
public function __construct() {
**//this part includes some protection or similar by default ?**
$this->middleware('auth');
}
}
Middleware is used when you want to filter the HTTP requests entering your application.
For example, including the built-in auth middleware will restrict non-authenticated users from accessing a page and redirect them to the login screen.
You can include middleware into your controller and routes.
In the controller you do it like so:
public function __construct()
{
$this->middleware('auth');
}
For a route you do this:
Route::get('/page', 'MyController#myMethod')->middleware('auth');
Do I need to include this part of code when I creating controller or not ?
As I said in my comment, it really depends on the desired functionality whether you use it or not.
An example
Your homepage should probably be accessible for anyone who visits you website, while your dashboard should only be displayed to authenticated users.
That's where you would include the auth middleware.
Question #1
Do you need to use $this->middleware('auth'); in your controller?
Answer: Only if you want to protect all of the methods of that controller from non-authenticated users and only allow signed in users to access controller actions.
Question #2
Do you get benefits for using the auth middleware?
Answer: Yes you do, only authenticated users can access the controller or routes protected by auth.
** Question #3**
Do you need to write your own middleware?
Answer: Only if you need to override a middleware or need extra functionality that is not already provided (php artisan make:auth), but if you are rolling your own login functionality then you will likely need/want to create your own middleware.
Resources:
Look in App\Http\Kernel.php and you will see that the $routeMiddleware array matches the auth middleware to the \Illuminate\Auth\Middleware\Authenticate::class which actually verifies that the current user is logged in and allows them to pass, if they are not logged in then it will redirect them to the '/login' route.
You will see that Laravel uses quite a bit of middleware by default, such as starting the session, encrypting cookies and protecting against CSRF forgery.
There are several ways to implement middleware, which I'm sure you saw in the docs.
Some Helpful Video Tutorials:
I suggest you watch each of the free series usually titled Laravel from Scratch on Laracasts.com. I would also suggest watching all of from Laravel 5.7 back to 5.1 or 5.0 as Jeffrey Way may use different techniques in similar situations and it will provide you with a great tips and helpful information as to how things work along with some Laravel best practices along the way. I've subscribed to him for years and work in Laravel everyday and I still learn some new things from watching his videos, a subscription is easily worth 10-20 what he charges.

how to convert my laravel project to an api?

I have a laravel project, which is about Students and their courses.
This project has CRUD functions, where the user(mainly the school's admin) can create users and assign their courses. I have successfully created this project.
But now how do I make this an API?. I need to share the students courses to another website, therefore I need to create an API right?
I have never created an API in laravel, when I checked the documentation of Laravel, it has this topic called API authentication using passport, is this talking about requiring users to login first before accessing the API
?.
Would be very helpful if someone can explain a little bit about creating an API and where to start from.
You are trying to give another website access to view the students courses. Is the data publicly available ? If yes, you don't need Authentication. But that means literally everybody with the API URL can access the data. Using Authentication on your API is entirely up to you.
Now, to create an API, it's very easy with Laravel. There are tons of free resources online like this one: https://tutorials.kode-blog.com/laravel-5-rest-api. Just google the topic for more.
Basically, the API works exactly like what you did in terms of controller and routing. In laravel 5.4, there is a separate route file for api located in routes/api.php. That's where you define your routes.
Route::get('courses', 'Api\CourseController#index');
This route will respond to https://www.website.com/api/courses and will link to the function index() located in app/Http/Controllers/Api/CourseController.php. You will have to create that controller yourself.
Looking at that route file, you can see something out of the box
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
It means the route /api/user will require authentication because of the auth:api middleware.
In your controllers so far, you return views. In api controller you will return response
public function index()
{
$courses = Course::all();
return response()->json($courses);
}
The application calling the website will receive a JSON object containing an array of courses. More about responses here: https://laravel.com/docs/5.4/responses
About api_token
The default API authentication offered by laravel works by checking api_token attribute from the users table. That api_token has to been present in the headers of the request sent to the api. Laravel will then use that api_token to identify the user making the request. In default application, to get a user, you do
$user = Auth::user();
Within your API controllers, you do
$user = Auth::guard('api')->user();
//Auth will look for api_token to get the user making the request

Laravel 5.1 - creating records from form data plus added data

I'm setting up a Laravel app that has a system where a user is created in an admin panel and then the user is emailed a link to login to the site and set up their details etc.
So, I have a route to handle creation of the user which looks like this:
public function store(UsersRequest $request)
{
$user = User::create($request->all());
event(new UserWasCreated($user));
return redirect('/users');
}
So as you can see, the user is created from the request object which hold their username, first name, last name, email address and password.
What I'm aiming to do is also randomly generate a hash that will also be inserted in to the database. Now I can do this in the controller but I want to keep my controllers as skinny as possible.
So my thoughts are that I'll need to create some sort of class that is responsible for setting up the user. What I'm not sure of is how to approach this and where to put that class. I'm thinking along the lines of creating a service provider to handle this and using that in the controller.
Does that sound like a sensible way to approach this or is their other (better?) options that I could explore?
Thanks!
The easiest way to do this would be to use the creating event which automatically fires during the creation of an Eloquent model.
You can either use the boot() method of an existing a service provider or create a new one, or place this in the boot method of the User model itself.
User::creating(function ($user) {
// Or some other way of generating a random hash
$user->hash = md5(uniqid(mt_rand(), true));
});
There are several other events which can be used, all of which are documented on the Eloquent manual page.
http://laravel.com/docs/5.1/eloquent#events

Codeigniter - Authentication Library or Custom Controller?

I'm wondering what is best in my case. I'm building a site using CodeIgniter with two main sections:
the public part avalaible to everyone
the private one only for registered users
In each page of the public area (one controller) I want to put a sign in form and a sign up link and if the users is logged in he has to be redirected to the private area or a link to it may be shown.
Now I have two choices:
A user controller is the first thing I thought of but in each page of the site I need to control if the user is logged and this is impossible or very bad since I'm using another Controller
So I started working on a library but I'm not sure how implement it (for example form validation should be achieved by the controller or by the library itself?, what about database connection since I haven't a model?)
What do you think is the best? Why? and how would you implement it?
(and yes I like reinventing the wheel and not using an existing library mainly because i want to learn how to do it)
Super Controller
=>assign user data,settings,configs etc
|-----private controller extends super controller
=>check user credentials
|-----admin controller extends super controller
=>check user && admin credentials
Your super controller is your public controller as long as you only do assignments, no checking...
Anything you want public just extends super controller
Anything you want private extends private controller
Form validations and query jobs should be carried out with the controller itself. The library act like a tool no need to implement these things in them but as a need you can use queries in them to check some data but it's better to be worked in the controllers.
The idea for having a log flag is to:
When user is signed in, create a session for it to show the access.
Check every time the session for the private parts.

Categories