REST API ROUTE PATHS - best practice for authenticated resource? - php

I have an API built with Laravel that works with authentication tokens (the passport package). It is unclear to me what should be the best practice for resources that are accessed within an authenticated session.
Let me explain.
Let's say I would like to see the orders of a user as an administrator, I visit: /v1/users/5/orders and all orders get listed for user with ID 5.
But now the user with ID 5 is authenticated. What should the URL be to access his own orders resource?
Would that be: /v1/users/5/orders (and check if it's either an admin or the session belongs to the user with ID of 5)
OR /v1/my/orders
OR /v1/my-orders
OR /v1/orders (and use session ID of user 5, - OR list all results when admin)
It just gets confusing when on the same URL the orders can be listed because an admin wants to access it. Or it is actually the session user that wants to see them.

I would suggest using /v1/orders, that will display a collection of orders based on privileges:
- all orders in case of an admin session
- orders belonging to the authenticated user, in case of a less privileged user.
Adding a prefix like /my/orders or my-orders does not bring any value.
For the sub-collections I would keep the route /v1/users/5/orders that will allow admin to access user orders.
This is a pretty good tutorial that explains API resource naming: https://restfulapi.net/resource-naming/

Related

Work with multiple logged in users at the same time

I need to have multiple users logged in at the same time in Laravel. Similar to Google/Facebook but instead of switching between users/accounts work with all authenticated users simultaneously, similar to email apps where you can access email from all accounts from one list.
Structure:
Unique auth credentials A
-Account 1 (aka tenant)
Unique auth credentials B
-Account 2
-Account 3
While not building completely custom solution in Laravel, I can’t think of anything rather than start using User model for authentication purposes only and adding next authenticated user ids to the first logged in session to handle multiple users. But it just feels like a hack.
Has anyone have any ideas or past experience with multiple authenticated users?

Laravel - multiple accounts with multiple users and separated data

I have done a lot of reading on this but nothing stands out. I already have a authentication and authorisation system that can handle multiple guards and user roles (user, admin, super admin etc.)
I am trying to find out what is the best way to separate the system into totally separate accounts which have the following;
No login section
Landing page. Anyone can see without login.
Admin Section
Admin side of the system has a super-admins and then multiple admin-users.
These users can see all data from every user who has an account on the client side.
Client Section
Each user account has an owner who deals with billing, their own user admin etc.
Each client account also has a number of users (admin-users, editor-users etc.) with varying permissions.
Users on this side should only ever be able to see their own accounts data. They should not be able to ever see other accounts data.
Before Laravel, I would have an accounts table and assign a unique key to each account. Then a separate users table would contain the user along with their account key.
All database tables from this point onwards (posts, products, shipments etc.) would also have this key to ensure that the user account could only see their own data.
On top of this there would be permission tables, for granular control of what each user from either side can see.
Is my original way still suited to Laravel or is there a better way?
To separate out the accounts into their own "ecosystems" within the same code base is called multi tenancy. Basically, you scope your applications queries based on the user id and/or role which limits the available data to any given user.
Have a look at the Landlord Package.
In a very basic summary, what it does is add a where('tenant_id, auth()->id()) clause to every applicable query.
You can of course either omit the clause entirely for super admins to access all data, or apply even tighter constraints, say by adding a check for the user's role in addition to the clause, further limiting what a user can access within their respective account/organization/group etc.
Scoping can be done by any kind of relationship, you're not necessarily limited to the authenticated user's id. If your application has organizations for multiple user's you can use the organization id.
Multiple tenant ids is also possible, where a user must belong to an organization and a certain division within that organization.
Another package I've used previously is Hyn's multi-tenant.
We have same project as you mention . We create a company table and put it on the top of the hierarchy.
Then add new field all tables as company_id
And manage models over Policy -> https://laravel.com/docs/5.8/authorization
I hope this help

3 Levels of Authentication / Middleware Laravel

Scenario
Im building an application that offers 3 levels of paid services but im not sure how to go about coding the 3 level functionality.
So for example if my app allowed users to post content to a page, and the 3 levels allowed you to post 1,5 and 10 times a month would i just set up a database that stores the data and then create Middleware to check the amount of times posted / the users post level etc. Im just not 100% certain im going about this right and was wondering if laravel offered any alternatives that i may have overlooked.
Question
Should I use middleware to control user levels or does laravel offer alternative and more specific methods?
Consider implementing user roles which correspond to each membership level (i.e. the first role could be 'basic user', the second role could be 'intermediate user', and the third role could be 'advanced user') if you don't want to go with the suggested policies route. Roles can be set up in Laravel using existing packages such as Entrust and Sentinel. In your users table, you should have a user name and role id (foreign key to a role), in your posts table you should have a user id (foreign key to a user) for each post and in your roles table store a post limit against each role (or store it somewhere in the application as a constant/config). When a user attempts to create a new post, you can do a count of all posts they've already submitted, e.g.
App\User::findById(1)->posts->count();
or consider using withCount() if you don't want to actually load them. Then follow this up with a check for how many posts the user is limited to, e.g.
User::findById(1)->role->postLimit
A comparison between the two should allow you to determine whether or not the user is able to continue posting.

Ways of restrict user based on user level in PHP

I have seen Joomla using many types of user access for the admin site. For example user, admin user, registered user and super user. The system actually know what type of user you are once we logged in. I'm trying to do the same thing for my web app. I need any suggestions on how this features can be achieved using PHP.
Assuming a user is in a database, you could have an column like role which would be user, admin, registered, and super.
Then in PHP you can use switch / if-condition blocks based on that role variable.

Multiple authentication systems

I've 2 tables, Users and Customers and 2 different actions for them. so I need 2 authentication system. Users login with username and password, and customers login with and id and password.
I know cake default AuthComponent can handle just 1 model, User model. because 'userModel' can be string not array (isn't it?).
How can I use it with 2 models (and tables) with 2 login pages and 2 .... .
(note: I can't combine the 2 tables. they have different schemas)
Instead of trying to maintain 2 different Auth systems, I highly recommend you look into ACLs and AROs. This will allow you to associate users with different access groups - in your case you could have groups like 'Internal'1 and 'Customers', and each new user account is a member of one group or the other.
You can then grant permissions at a group level. Customer users have access to their content, Internal users have access to different content.
There is a good tutorial in the new CakePHP book: Simple Acl controlled Application
1 I assume when you refer to 'users' generically you mean internal users, but feel free to adapt the terminology and group names to your particular situation.
I would presume 2 separate logins areas or a radio button to suggest which login they are attempting.
Use that input as which table to auth against then your code should follow the same path.
if (customer) {
do customer stuff;
} elseif (user) {
do user stuff;
} else {
you didn't login;
}
When you create the registration forms for them try to get their data into different databases. So that you can treat them differently. For this purpose check the submit button ids and direct the data to appropriate tables. When inserting put id's as auto increments.
I would advise against discriminating users from customers in this situation. These issues can be resolved using roles. Before jumping to design, please read about Authentication, Authorization and Audit and Role-Based Access Control.
From my understanding, this is an overview of the authentication process (note that I am not a security expert):
The identification phase is concerned with obtaining user credentials. A simple form that retreives user's name and password would suffice.
The authentication phase represents the process that maps user credentials to an user. Basically, it identifies a identity provider and uses it to obtain an user id for the user credentials provided.
Viewed like services, they look something like this:
// You can have many IdentityProviders. This mecanism allows you to extend your
// authentication system so you can use any mechanism (WebDav, Kerberos, etc).
IIdentityProvider
{
// Returns a pozitive id if the user is found and the credentials are valid
// or zero if user credentials are invalid (or negative numbers that represent
// error codes).
UserID GetUser(UserCredentials)
}
IAuthenticationService
{
Session SignIn(UserCredentials)
void SignOut(Session)
}
DefaultIdentityProvider : IIdentityProvider
{
// Search the user in your database.
UserID GetUser(UserCredentials credentials)
}
AuthenticationService : IAuthenticationService
{
IIdentityProvider[] identityProviders
Session SignIn(UserCredentials credentials)
{
IIdentityProvider provider = identityProviders[credentials.Type]
Session session = null
if (provider)
{
UserID userID = provider.GetUser(credentials)
if (userID > 0)
{
session = new Session
session.UserID = userID
}
}
return session
}
void SignOut(Session session)
{
delete session
}
}
The autorization system says what can a user do with a resource. Resources can be any entity that your application manages. They have a type and an ID. Optionally, they can be part of one or more categories. Users can execute certain operations on a resource, depending on its type and categories. This is defined by a permission. Permissions are grouped in roles. You can assign zero or more roles to an user.
In your example, a customer is a role. A resource is, for example, a product. A product is represented by the Product type, it has an ID and can have some categories associated ("Electronics" and "Dangerous"). Operations can be viewed as variations of Create/Read/Update/Delete verbs. Now, the Customer role would contain a set of permissions that explicitely states what a user having this role can do with the managed resources. For example, a Customer can only Read certain informations about the product, but cannot Create, Update or Delete a product. Note that if a user has more than one role associated, it gains all the permissions from that roles (an union operation, not an intersection).
This only scratches the surface. For further reading, you can find on the Internet more articles that explain these concepts alot better. This is meant to point you in the right direction.

Categories