Let's say that you have an image I that you only want users who have logged into your website to be able to see. What is the best way to protect I from non-logged in users. One possible way is to have a page where you pass the image name via get or post parameters, and it would return the image by reading the image from disk and writing back in the response based on if the user was logged in the session. Is/Are there better ways to achieve security of resources more efficiently?
use your session. when the user is logged in, you load the image to your page.
There are couple easy ways you could to this with servlet filters or just plain servlet that servers your resource.
Personally I would check if the principal have been set is so then you know the user is authenitcated
Principal principal = request.getUserPrincipal();
if (principal == null) {
return null;
}
If there is no principal you know the user is not authenticated, you could return 403 status, blank image or whatever you like.
If you want to protect the urls of the image files, set some rules about their access in your code. I think a better alternative is using some security framework. There are some security platforms like Spring Security provide very comprehensive access rules based on user authentication status, url-role combination, and acl, etc..
Related
I have a Spring Boot REST API that I'm building. Im slightly stuck on the correct way to design my API in a way that protects each individual users' data. For example, consider the following database relations:
User -> (Has Many) Projects -> (Has Many) Tasks. (A User has-many Projects, and a Project has-many tasks).
For example, if I design my endpoints in the following way:
GET /api/v1/projects/{projectId}
POST /api/v1/projects/{projectId}/tasks
Just as a simple example for the above, how can I make sure, when creating new tasks for a certain project, that the project belongs to the logged in user?
Currently, I am using JWT tokens via Spring Security as my authentication strategy, and included in the payload of the token I have my Users' id. So with every request I can retrieve the user, but surely that's incredibly inefficient to be making so many requests to the database and check if the user actually has a given project.
Some solution I was thinking about is to simply have endpoints designed like this:
/api/v1/users/{userId}/projects/{projectId}/tasks
And then I can use the user id in the JWT payload and compare it to the user id in the request parameter. But then that would mean with every new relation in my database, the length of the url is going to be massive :) Also I guess it would mean all the business logic would be inside the User service for the whole application, right? Which seems a little odd to me... but maybe I'm wrong.
Im not sure if thats an issue or not, but just trying to design the API to be as elegant as possible.
Thanks again!
Checking if the user has permissions to a project on every request is the correct solution. Consider cases when many other applications / users are calling your API. You want to make sure that your API is as secure as possible and cannot be manipulated from the frontend.
To make it more efficient you should have a way/query to check associations in your database like a simple query that returns true/false which should be quicker than retrieving all the data and comparing in Java code.
And when possible combine multiple database queries into one, like for one of your examples:
GET /api/v1/projects/{projectId}
in this case, don't run a query to get a user's information and a query for the requested project. Instead you could do a single query with a join between the user's table and the project table which should only return a project if the user is associated with it. The best way really depends on how your database is structured.
Adding a user id into the API URL is just redundant information. Just because the user id in the token matches the user id in the URL doesn't mean the user has any kind of permissions to any project.
Another solution to be avoided is to include the user's project ids in the JWT token which you can then compare without making a database request. This is bad for several reasons:
The token should only have required information for the user to access the API, it shouldn't have business logic
Depending on how much business logic you store in the token the token can become large in size. See this post for a discussion on size limits: What is the maximum size of JWT token?
If there is a way for the someone other than the user (like admin) to add/remove a user's association to a project then that change will not be reflected in the token until the token's data is refreshed
EDIT:
On the spring side I have used the #PreAuthorize annotation before to handle these types of method checks. Below is pseudo code as an example.
#RestController
public class MyController {
#PostMapping
#PreAuthorize("#mySecurityService.isAllowed(principal, #in)")
public SomeResponseType api1(SomeRequestType requestData) {
/* this is not reached unless mySecurityService.isAllowed
returns true, instead a user gets a 401/403 HTTP response
code (i don't remember the exact one) */
}
}
#Service
public class MySecurityService {
/*
Object principal - this is spring's UserDetails object that is
returned from the AuthenticationProvider. So basically a Java
representation of the JWT token which should have the
user's username.
SomeRequestType requestData - this is the request data that was
sent to the API. I'm sure there is a way to get the project ID
from the URL here as well.
*/
public boolean isAllowed(Object principal, SomeRequestType requestData) {
/*
take the user's username from the principal, take the
project ID from the request data and query the database
to check authorization, return true if authorized
make this check efficient
*/
return false;
}
}
The annotation and the security service can then be applied to multiple methods. You can have many different security services depending on what your are checking.
There are other ways available too https://www.baeldung.com/spring-security-method-security and this has to be enabled in spring's configuration (also explained in the link).
Hi so if I understood it correctly you want to automatically assign the task that is going to be created with "POST /api/v1/projects/{projectId}/tasks" to the current logged in user.
You could try to add a Parameter 'Principal principal' to your rest controller. The Principal is the user that is sending the request.
After you have your Prinicipal, you could write a simple convert method(for example: convertPrincipalToUser(Principal principal) which returns you the user. Finally you can add your user to the corresponding task)
Here is some more information about it:
https://www.baeldung.com/get-user-in-spring-security
I am working on a legacy (struts 1.1 running in jdk 1.4 , tomcat 6)application and need advice for implementing user role based security.
A user u1 has a read/view permission while user u2 has write permission on certain action. E.g
Url for user u1 :
http://www.somedomain.com:8080/app?key=12
(It shows the content related with key 12 from DB).
Url for user u2 :
http://www.somedomain.com:8080/app?key=12¬e=some note test
(It basically insert note value in DB for key 12)
Suppose if user u1 who has view rights, come to know the url used by u2, he can insert any malicious value for particular key, which he is not suppose to do.
Even though role based access to struts action class is in place , here the action class used by both users are same and only difference is url parameter.
Now I have to fix this issue, which is spread across thousands of action classes.So adding checking conditions in each and every action class will not be feasible.
I am thinking of writing a filter class which will read user role and allowed request parameter(with possible values like action='save' action='view') from a configuration file.
Are there any alternative solution approach?
your best choice is to modify the action class and implement some check inside called method (you can mixup container role-based permissions)
public void perform(HttpServletRequest request)
{
String note = request.getParameter("note");
if(!request.isUserInRole("writer") && note != null) throw new SecurityException("not allowed");
...
}
Without knowing much about your application, but I would try to apply java declarative security for my role based solution as much as possible.
If it is easy for you to use the java ee declarative security then go for it.
It is simple, flexible and using standards which will give you the safety you request and the ability to port your solution to different java web server providers.
Maybe a url rewriter (apache in front of the web application can help to reorganize); can split the destinations, and for that in your java web server set the url patterns which will expect different user roles for the read/view and update/write grantings permissions.
This will need some few changes to achieve, but you would definitely not need to change your 4k codebase and you will by this reach a clean solution.
Search for e.g. setting up role based security or java declarative security
some reading with demo...
http://www.thecoderscorner.com/team-blog/hosting-servers/17-setting-up-role-based-security-in-tomcat#.Us0eShoeK-Y
I working on Spring MVC app. The app funcionality is accessible through ReST API which jsp containing ajax logic consume. I am using spring security with defined roles (USER, COMPANY, ADMIN). Methods use requestMapping with responseBody such as:
www.app.com/auth/{userId}/request/{requestId}
It, of course, support GET for obtaining resource and POST for its creating or updating.
The problem is that after succesful login with, for example, userId = 1 I want GET request with requestId = 99. But when I run WebDev client for Chrome, I can also access another resource with easy request in format
www.app.com/auth/5/request/{requestId}
So basically, I can access resources, which I am not allowed to see. I hope you got the idea, where I am heading.
My question is - What is the best approach to secure this?
I was thinking about storing logged user Id (Integer) in session and comparing it everytime request for resource is made, but it seems to me that I am pulling the wrong end of rope :)
Thank you for any advice
You should have a look into the Expression-Based Access Control section of the spring security documentation.
Example copied from the documentation:
#PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact) {
..
}
This would check if name of the contact is equal to the name of the currently logged in user.
Using this this feature you can build much more sophisticated access rules than you could do with simple roles. However, this does not exclude using roles. You can still keep roles for basic security checks.
We implemented OWASP's CSRFGuard to protect our pages in the web application. For example */myCsrfProtected.jsp. We have injected CSRF token at all occurrences of */myCsrfProtected.jsp within the application. Everything works fine.
However, we have other use case where the link to this protected page is sent out to users in an email. Think about a link to a report. Now when user clicks on this link, the token is missing or invalid and hence the CSRFGuard filter blocks the request assuming this to be a CSRF attack. (this is what filter has been implemented for :-) )
Is there any way to handle this use case and allow access to CSRF protected page from outside the application.
Ideally a CSRF token check would need to performed only for POST requests. GET requests are supposed to be idempotent((no side effects on server, just return some data no transactions performed on behalf of the user).
If all you want to do is return a report when the user clicks on link you might not need a csrf check to be performed. You might still want to make sure the user is authorised. You should be able to by pass the CSRF check for this request
Can the JSP servlet that filters on *.jsp (org.apache.jasper.servlet.JspServlet in Tomcat 6) be extended in some way so whenever someone goes to a JSP page I can do some server side authentication to check whether the user can view the page. Our current technique is a taglib in a common include that is imported into each JSP page, but it's not very elegant.
The key here is that I don't want to reinvent the wheel and worry about compiling JSPs into Servlets, I would ideally like to delegate in each method with super.meth().
I've been searching Google but I don't know the right keywords to use. Anything containing JSP and Servlet returns beginner tutorials.
Thanks,
John
Look at Servlet Filters, and use that Filter before forwarding to some JSP or Servlet.
When not taking benefit of the Java EE provided container managed security, then the normal basic practice is that you store the logged-in User in the session scope and uses a Filter on the desired url-pattern to check if the User is logged in.
Here's a basic example to get the picture:
Login:
User user = userDAO.find(username, password);
if (user != null) {
session.setAttribute("user", user);
} else {
// Do your thing to show "Unknown login" error.
}
Filter (which is mapped on an url-pattern of for example /secured/*, /protected/*, etc where in you place the restricted JSP pages expect of the login page):
User user = session.getAttribute("user");
if (user != null) {
chain.doFilter(request, response); // Logged in, so continue with request.
} else {
response.sendRedirect("login"); // Not logged in, redirect to login page.
}
Logout:
session.removeAttribute("user");
// Or, a bit too drastically:
session.invalidate();
You can of course also take benefit of what Java EE out of the box provides with regard to security. A commonly used way is the declarative container managed security wherein you can specify users and roles. You just need to declare a <security-constraint> and a <login-config> in the web.xml and configure an user realm in the appserver. The details depends on the appserver used, but if it is for example Tomcat 6.0, then you can find here some documentation about that.
If basic auth isn't sufficient, maybe Spring Security would be better. It's a natural, especially if you're already using Spring. One big advantage is that it's declarative, so you can easily protect URLs just by adding them to security configuration.
Doing this via inheritance would be brittle and require code changes every time you modified your security. Best to have security as a cross-cutting concern.
Can you not create another filter and put it above JspServlet?
This filter would check your security stuff and do some handling (e.g. redirect to login page) if something is wrong.