There are many reasons not to use basic authentication scheme to protect Web API services.
In order to use the service, the client needs to keep the password somewhere in clear text to send it along with each request.
The verification of a password should be very slow (to counter brute force attacks), which would hamper scalability of your service. On the other hand, security token validation can be quick (digital signature verification).
OAuth2 does offer solutions for each of your use cases. Your web application can use the code grant, which gives it an access token it can use to talk to your API.
Your web application will redirect the user's browser to the authorization server. It will prompt the user for credentials (or smart card, or two-factor auth code) and return a code to the browser, which the client (your web application) can use to get an access token from the authorization server.
Your application will also get back a refresh token with which it can get a new access token if the current token expires.
Your CLI application can use the resource owner credentials grant. You will prompt the user for credentials and submit them to the authorization server to acquire an access and refresh token. Once your CLI application has the token, you can discard the user's password in memory.
Both clients (web app and command-line client) need to be registered up front with the authorization server.
Your authorization server may well talk to a LDAP/directory service (identity provider or IdP) to do the actual authentication.
Your web API service only needs to verify the incoming JWT token and establish what the user is allowed to do (authorization).
If you are the victim of a man-in-the-middle attack and you lose your access token, the attacker only has a limited time (token lifetime) to use it. A password is typically valid for much longer. Refresh tokens can be revoked in case they get lost.
Disclaimer: I am by not way an expert on these kind of matters, I'm just sharing how me and my senior are doing our current project.
Database:
Your design looks solid enough, but I would think about how I would hold these permissions in a table.
lets say we have a users
table
user_id | name | password
-------------------------
0 | John | ****
I can see 2 possible ways you would extend our database to hold these permissions.
You can add permission columns that tell what each user can do
user_id | name | password| perm1 | perm2 | ... |permn
------------------------------------------------------
0 | John | ****| Y | N | | Y
That will entail having a lot of columns and a messy design. on the plus side you will have the granularity to dictate exactly what one can and cannot do.
You can however add the concept of roles
to your design.
You can make a roles
table, define the types of user roles (and the kind of permissions they provide) in your application and just give each user a role
user_id | name | password| role_id
-----------------------------------
0 | John | ****| 1
And the roles
table
role_id | role_name | perm1 |....| permn
----------------------------------------
0 | Admin | Y | | Y
1 | Regular | N | | Y
This way you create a separation of concerns for your users table, instead of placing all your user data into one table that may grow over time (handling dozens of columns in a table is no fun), you can place separate relevant user data across multiple tables. it will also keep your queries short.
(This is similar to how Java web applications provide privileges/permissions to users)
PHP:
For your client view, you can hold a session object that describes the current user, you can use the role
value to tell your php scripts what parts of your templates you want to generate for your user.
Example (blade):
@if (user($role) === 'admin')
<button id="dontclickme">History eraser button</button>
@endif
Best Answer
It depends on what you mean by "permissions". I will present some ideas with an example with User and Project resources.
If the permissions are independent of a given Project, then you are really talking about the User having a role (e.g. admin). This can be encoded in the API representation of that User.
If the permissions are dependent on the underlying resource (e.g. a User can have different permissions for a given Project) these can reside in the API representation for that resource. This has the pro that you don't need a huge dictionary of all of a user's permissions and the con that any caching of that resource need to be user specific. This may be an acceptable trade off.
You still have a potential usability issue with stale data if someone loads a view and their permissions for the viewed resource change before they attempt an action. One way to try to mitigate this is to use websockets to push updates to viewed resources to try and reduce the window during which the UI will be out of date with the backend database.