Separate Controller for Admin Panel in REST API - spring

I'm currently working on REST API using Spring Boot. Let's say i have product service with basic functionality in controller. There are two roles in user which are normal user and admin.
example:addProduct, getProduct, updateProduct, deleteProduct
User can only access getProduct endpoint and admin can access all endpoints.
Which one is better apporoach?
first approach:
api/v1/products/ -> do all get, post, delete, patch
second approach:
api/v1/products/admin -> get, post, delete, patch
api/v1/products -> get

I suggest using a Role-Based Access Control (RBAC) wherein each user has a role. and each role has permissions, e.g. get_post, delete_post, and so on. As your application gets bigger in scope, you can have fewer routes in this way.
Example situation: if a user posted a resource on api/v1/products, the system will check if the user has a "create_product" permission. If he has no access then your api should return 401 unauthorized

Related

How to access user specific resources in webapi when the access token does not include user info

I have implemented OpenId Connect for authorizing my multi tenant app, I have obtained both the Id Token and the access token. The access token does not contain any claims, but I would like to access user specific resources in the web api.
For example, in order for a user to access a certain resource, 1. They must be a tenant admin and 2, they must have permission for that resource (say a specific job post).
My questions.
Do I send the user permissions to the webapi in the request body/query and the webapi trust those permissions?
Should I use the access token to call the Identity Server to get the user information, then proceed if the user has the permissions?
Any other options?
You can always add the necessary user claims inside the access token, and by doing that, you don't have to pass that information separately. You use ApiScopes and APiResources to control what user claims that goes into the access token.
See my answer here: ApiResource vs ApiScope vs IdentityResource
To complement this answer, I write a blog post that goes into more detail about this topic:
IdentityServer – IdentityResource vs. ApiResource vs. ApiScope

Spring Boot Security registration and logging for website with roles, how to do it?

I have a difficulty in understanding Spring Security and any tutorial I found was not tailored to my needs. So maybe I'll explain what I think and what I want to accomplish.
I want to create a website with Kotlin/Java backend and frontend in React. This website would need to have users with different roles (user, admin).
And (I think) the thing I need is some kind of backend that has 2 endpoints:
register (to create users in database)
login (to, based on username and password, fetch user info and role) - as some kind of token? This returned token would be then used by frontend to display specific options (i.e. do not display "ban user" for regular users) and it also would be sent to backend for checking if the person who requests for specific endpoint really should be able to call this endpoint (i.e. it should be forbidden for regular users to use "ban user" endpoint)
What should I read about, what keywords should I look into to achieve this?
For purely the Spring Boot part of the implementation, the following should do
(/register) Signup/Register endpoint taking all required parameters for your business logic. e.g Username , Password , Full Name as well the roles
(/login) For logging in , you need a token forwarded to the front end, which will then use this token in the header for the session. JWT tokens seems like what you need(sample below). For the other part of your requirement, you can keep the user object (with roles) in the session as well as check user role on the backend in the "ban user" endpoint and process accordingly.
JWT Authentication with Spring Boot
I found a good starting point in the following sample
https://github.com/bezkoder/spring-boot-spring-security-jwt-authentication
For a more complete example
https://www.bezkoder.com/spring-boot-react-jwt-auth/
Credits to
https://www.bezkoder.com/
I have come a cross Youtube Video that covers all the scenarios that your looking for and extra, with Email verification links as well. i hope this will definitely help you
Java Tutorial - Complete User Login and Registration Backend + Email Verification

Laravel 5 - Authentication with Login-Form (users) and API-Request (students)

I want to authenticate normal users (users-table) with login form and laravel auth.
Additionally I want to authenticate students (students-table) with API-request like:
mylaravelsite.com/?studentkey=XXXXXXXXXXXXXXXXXX&studentname=YYYYY
How can I do this? I think with a middleware?
How can I use the Auth class to check if the logged in person is user or student or guest?
I like to build applications in the following way:
A route having a single purpose, meaning, one route is for authenticating users and another route is for authenticating students
Validating data on the middleware before performing ANY operation
Now to your question:
If you really need, you can create different routes linked to the same authentication method, and create a middleware to each where you 'manipulate' run-type which class the Auth is going to be used
auth()->getProvider()->setModel(App\Student::class);
There are other ways to do this, depending on the way you wish to authenticate. If you want a more detailed explanation, give us a scenario to work on:
How the user authenticates vs how the student authenticates
What is going to differ from these 2 authentications and how its handled
Note: You're authenticating users with a HTTP request to a certain route, which is the same as your example link, except that you're giving an HTTPGET example and default is POST on authentication

Multiple middlewares do not work as wanted

If I have 3 user roles (head, admin and moderator):
I want to allow head to all methods, admin to most methods and moderator to one method.
Inside InstitutionsController:
public function __construct() {
$this->middleware('head');
$this->middleware('admin')->only(['index', 'create']);
$this->middleware('moderator')->only(['index']);
}
By this I cannot open visit index method as moderator or admin, just as head...
How can I achieve this?
BTW my middlewares have: return !auth()->user()->isAdmin()?redirect()->home():$next($request) etc for other 2
You need to read up on middleware. They are classes that manipulate HTTP requests and responses. A request comes in, a response comes out. They’re processed one at a time. So if you have a middleware that checks a role, it’s going to check that role and throw an “Unauthorized” response if the user does not have that role.
As such, checking if a user can do something is not the job of middleware (as you have found). If you want to check a user can do something, use a policy around your resource instead.
The Authorization documentation has more information on creating policies and authorizing actions in your Laravel applications.

Programmatic authentication

I am using Spring Security in my application.
I have all the pages secured. But couple of URL needs to be available both for system user and anonymous user.
But anonymous user should not have direct access to the URLs. He gets a link with unique token and gets access to some URLS if this token is valid.
What I want to do is:
In controller check if token in URL is valid
If it is - authenticate user in the system programmatically using some predefined login and password. This user will be configured to have authority to access necessary URLs.
The question is:
Is this a correct approach to perform user authentication programatically with some roles in controller if token is valid? Is this safe approach?
Security is an aspect. An aspect can be decoupled from your main code (controller) to reduce code duplication and improve flexibility. Move authentication code from controller to new filter (be sure that this filter executed after spring security filter chain). You will be able secure new URLs via web.xml (zero lines of code).
I think the better way to do this is:
move the shared operations into service layer
define a controller for those anonymous user and make its authority
as anonymous
check the validity of token in this controller
if valid, call some services method to perform the operations.
render the result in this controller

Resources