I am new to spring security framework.I was just compiling the various ways to add security features using spring security annotations or spring security framework.
Found the below so far.
Full Page Authorization
example: <intercept-url pattern="/user/**" access="hasRole('ROLE_USER')" />
In-Page Authorization
example : <security:authorize access="hasRole('ROLE_ADMIN')">
Method Level Authorization - #PreAuthorize,#PostAuthorize,#PreFilter,#PostFilter
I am not sure if this is an exhaustive list to secure the application. Need some help for the same. Thanks.
Also,I am looking for security features which can easily be implemented and configurable- where developers are less likely to make mistakes and at the same time achieve the required security goals.It looks like annotations are easy to use and less ambiguous. Are annotations used only for method level authorization? Does spring security provide annotations which can be used for securing other parts of the application and can these annotations be passed parameters to configure the permissions or privileges?
I hope my question is not too broad. Any edits or helpful comments would be appreciated.
Perhaps you need to start by identifying the requirements of your domain model, what is deemed sensitive data and what not and how this data is being accessed (HTML/JSP vs REST/JSON vs direct Java calls). Then use the authorization features as needed. Your list contains pretty much what most applications will ever need, but for finer and more advanced authorization mechanisms have a look at Spring's ACL:
http://docs.spring.io/spring-security/site/docs/3.0.x/reference/domain-acls.html
Another important question you may want to answer to yourself is which application layer will be responsible for enforcing your security: MVC/REST vs Services (scattering this concern across multiple layers is usually bad idea). This will directly dictate the choices of SS features you are going to make.
You may wish to build your own annotations on top of SS annotations which reflect closely your particular domain. This way all complexity will be concentrated in a single place, leaving less room for error.
For example, you can create a custom annotation such as #AuthorizedFor where you can add various domain-specific parameters. You then annotate this annotation with one of SS annotations, say #Pre/PostAuthorize("hasAnyRole()") (here you can also play with the Spring's native EL to further customise the behaviour) and use custom implementation of Pre/PostInvocationAuthorizationAdvice where you make the authorization decisions based on your custom annotation parameters. The added advantage here is that you will be able to secure complete classes with your custom annotation instead of having to annotate all methods in that class. In your implementation you get the MethodInvocation instance from where you can interrogate the class containing the method and see if its annotated, then proceed as-if the method itself was annotated.
See this article for more in-depth discussion: http://blog.novoj.net/2012/03/27/combining-custom-annotations-for-securing-methods-with-spring-security/
There are basically 2 ways to implement spring security. through bean configuration in .xml files and other by using Annotations. Annotation based method is easy to use in long term as it is less ambiguous.
here is the reference to spring.io . Both ways are explained nicely.
http://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/
Annotation is pure java based configuration and will most probably overtake xml configuration.
The three items in your list serve different purposes:
intercept-url : Adds security at the servlet layer. In other words, you control who can/cannot access any url in your application. For example you may add permission only to administrators to access the url /admin/some_critical_operation, but allow all authenticated users to access /some_informational_page. It is possible to secure your application with this type of authorisation only but it is very fragile design. Adding or changing urls can easily break security without notice.
In-Page Authorization: It is not real authorisation, just a convenience tag for hiding html content not intended for the current user. For example a non-admin user should not see the button create new user. As I said it is not real security measure since the user can type the url in the browser and gain access if none of the other authorisation types have been applied.
Method Level Authorization: Adds security to the service layer. This means you can apply restrictions on who can/cannot call a method of some service class. It is considered more secure and harder to compromise since it is applied deeper in the application layer stack. It can be applied both with annotations and with the security namespace.
Usually you start by securing your application in the service layer and then add some url control as well. Adding authorisation tags in pages is optional.
I can't comment yet, but regarding your question:
Are there annotations which are configurable? For example, I provided the method level security annotations where you provide the parameters - like the roles of users who have the privileges to access the method or to access the elements returned by the method
You are free to write your own annotations, which are in turn annotated with the native Spring Security annotations. This makes them essentially a domain-specific extension. That said, the standard SS annotations allow the use of SpEL which is rather flexible even tough is not bound to your particular domain. You can easily assert if user has certain roles (GrantedAuthority), etc ...
If you want to implement your own annotations, see the link in my other answer for a thorough discussion.
I can give you a concrete example from a recent project I worked on. We had authorization groups managed by external system and also built-in logic which defines access to certain resources. So, essentially we had 2 places to look for authorization parameters. We've created the concept of Authorization Groups (retrieved externally via LDAP) and Authorization Roles (built-in, business logic). The groups were simple - if user is a member of the group, they are granted access, else denied. With the roles, we had business rules which determine whether the user has a particular role or not (for example - signed T&C, accepted EULA, etc ...). All of these are determined at the authentication stage.
To make it easier to reason about our access control, we created two annotations #AuthorisedForGroups({group1, group2, ...}) and #AuthorisedForRoles({role1, role2,...}). Each of these was in turn annotated with Spring's native #PreAuthorize("hasAnyRole()"). Note the use of "hasAnyRole()" - this is simply to tell Spring "let everybody who is authenticated in" and that "we are going to make the authorization decisions ourselves". The authorization decisions are then made in a custom implementation of PreInvocationAuthorizationAdvice (in fact we just extended Spring's own implementation ExpressionBasedPreInvocationAdvice) and put the decision-making logic in #before() method:
#Override
public boolean before(Authentication authentication, MethodInvocation mi, PreInvocationAttribute attr) {
// 1) get AuthorisedForGroups & AuthorisedForRoles for the method
// 2) if either is missing from the method, check the enclosing class
// 3) if no annotations found - simply return super.before(...)
// 4) else, introspect the 'authentication' and see if it has the required groups/roles
// - here you may want to use 'ExpressionBasedAnnotationAttributeFactory' to
// create your own expressions which you then pass to super.before(...).
// This especially makes sense when your groups/roles
// are mapped to GrantedAuthority instances - as it was the case with our code.
}
Hope this helps.
Related
What are the differences of using Spring Data REST repository alone and implementing the “service” pattern around it (that is ItemService, ItemServiceImpl and so on)?
At the first glance the functionality is more or less the same with the difference that the service approach allows for a better customization but it also produces loads of boilerplate code (the implementation and the controller). Here is an example (look Payment and CreditCard entities) of using both approaches - RESTBucks of Oliver Drotbohm.
The payment abstraction there uses the "service" pattern used (PaymentService, PaymentImpl and then PaymentController with all methods in web folder) while the orders are exposed via Spring Data REST directly.
tl;dr
The payment functionality lives at a higher level of abstraction as it doesn't follow established HTTP resource patterns (collection resource, item resource, in general: the ones described here) and thus warrants a custom service implementation. In contrast, the lifecycle of the order aggregate does indeed follow those patterns and thus doesn't need anything but Spring Data REST exposure plus a few customizations. Find a conceptual overview about how the two implementation parts relate to each other here.
Details
That's a great question. The sample application is designed to showcase how different parts of an API can be driven by different requirements and how you can use Spring Data REST to take care of the parts that follow established patterns but at the same time augment it with higher level aspects that are needed to express business processes.
The application is split into two major parts: the order handling that's centered around the Order aggregate that is taken through different stages. A conceptual overview about those can be found here. So parts of our API for the orders will be following standard patterns: filterable collection resources to see all orders, add new orders etc. This is where Spring Data REST shines.
The payment part is different. It somehow needs to blend into both the URI and functional space of the order handling. We achieve that by the following steps:
We implement the required functionality in a dedicated service. The repository interaction doesn't match the necessary level of abstraction as we have to verify business constraints on both the Order and Payment aggregates. That logic needs to live somewhere: in the service.
We expose that functionality via a Spring MVC controller as we (currently) don't need standard patterns like listing all payments. Remember, the example is centered around modeling the ordering process, it's not an accounting backend. The payment resources are blended into the URI space of the orders: /orders/{id}/payment.
We use hypermedia elements to indicate when the functionality can be triggered by adding a link pointing to those resources conditionally so that clients can use the presence or absence of those elements to decide what UI affordances to offer to trigger that functionality.
Here's what I think is nice about this approach:
You only manually code the parts that are important from the business point of view. No need to implement a lot of boilerplate code for the parts of the API that follow well established patterns.
Clients don't need to care where exactly that seam is. Using hypermedia elements, the API just looks like one thing to the client. The server could even move the payment resources to a different URI space or a different service even.
Resources
This deck discusses what I described in detail. Here's a video recording of it. If you're interested in the higher level ideas of especially the drive towards hypermedia, I suggest this slide deck, too
Your service contains all the logic, but the repository layer is as stupid as possible. Its task is a specific operation(for ex. save, edit).
Spring Data is an additional convenient mechanism for interacting with database entities, organizing them in a repository, extracting data, changing it. in some cases, it will be enough to declare the interface and method in it, without implementing it.
P.S
and it's a good choice if you're creating a simple crud
For a restfull service, does the noun can be omitted and discarded?
Instead of /service/customers/555/orders/111
Can / should I expose: /service/555/111 ?
Is the first option mandatory or are there several options and this is debatable?
It's totally up to you, I think the nice thing about having the nouns is that it helps you see from the URL what the service is trying to achieve.
Also taking into account that under customer you can have something like below and from the URL you can distinguish between order and quote for a customer
/service/customers/555/quote/111
/service/customers/555/order/111
One of the core aspects of REST is that URLs should be treated as opaque entities. A client should never create a URL, just use URLs that have been supplied by the server. Only the server hosting the entities needs to know something about the URL structure.
So use the URL scheme that makes most sense to you when designing the service.
Regarding the options you mentioned:
Omitting the nouns makes it hard to extend your service if e.g. you want to add products, receipts or other entities.
Having the orders below the customers surprises me (but once again, that's up to you designing the service). I'd expect something like /service/customers/555 and /service/orders/1234567.
Anyway, the RESTful customer document returned from the service should contain links to his or her orders and vice versa (plus all other relevant relationships).
To a certain degree, the "rules" for nameing RESTful endpoints should follow the same naming rules that "Clean Code" for example teaches.
Meaning: names should mean something. And they should say what they mean, and mean what they say.
Coming from there: it probably depends on the nature of that service. If you only can "serve" customers - then you could omit the customer part - because that doesn't add (much) meaningful information. But what if you later want to serve other kinds of clients?
In other words: we can't tell you what is right for your application - because that depends on the requirements / goals of your environment.
And worth noting: do not only consider todays requirements. Step back and consider those "future grow paths" that seem most likely. And then make sure that the API you are defining today will work nicely with those future extensions that are most likely to happen.
Instead of /service/customers/555/orders/111
Can / should I expose: /service/555/111 ?
The question is broad but as you use REST paths to define nested information, that has to be as much explicit as required.
If providing long paths in the URL is a problem for you, as alternative provide the contextual information in the body of the request.
I think that the short way /service/555/111 lacks consistency.
Suppose that /service/555/111 correspond to invoke the service for the customer 555 and the order 111.
You know that. But the client of the API doesn't know necessarily what the paths meaning are.
Besides, suppose now that you wish invoke the invoke the same service for the customer 555 but for the year 2018. How do that now ?
Like that :
/service/555/2018 would be error prone as you will have to add a parameter to convey the last path value and service/555/years/2018 will make your API definition inconsistent.
Clarity, simplicity and consistency matters.
According to me usage of noun is not necessary or comes under any standard,but yes it's usage helps your endpoint to be more specific and simple to understand.
So if any nomenclature is making your URL more human readable or easy to understand then that type or URL I usually prefer to create and keep things simple. It also helps your service consumer who understand the functionality of any service partially by name itself.
Please follow https://restfulapi.net/resource-naming/ for the best practices.
For a restfull service, does the noun can be omitted and discarded?
Yes. REST doesn't care what spelling you use for your resource identifiers.
URL shorteners work just fine.
Choices of spelling are dictated by local convention, they are much like variables in that sense.
Ideally, the spellings are independent of the underlying domain and data models, so that you can change the models without changing the api. Jim Webber expressed the idea this way
The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.
Resources adapt your domain model for the web
That said, if you are expecting clients to discover URIs in your documentation (rather than by reading them out of well specified hypermedia responses), then its going to be a good idea to use URI spellings that follow a simple conceptual model.
I understand that using HttpServletRequest and HttpServletResponseobjects in an MVC-patterned web application has benefits e.g. interrogating HTTP request details and setting useful attributes for the view (e.g. JSPs) to use them. But is there any recommended practice for NOT using HttpServletRequest/Response objects in the design - and I mean in any specific places e.g.
1) Service Layer/DAO
2) Model
Recently I have had a code review from a peer who suggested that I should remove the usage of HttpServletRequest/Response objects from the service layer. Besides that fact that Service Layer is strictly for everyone to use (i.e. should not pass request/response objects like that), I cannot seem to see any other reason. Would anyone care to help and tick my brain?
KR,
I'd like to secure a simple rest web service developed using Jersey using Spring OAuth v1.0a, and I have a questions about it. First, a brief doubt: I've found some examples involving Spring-MVC, is it mandatory to include it? As I'm trying to make my application as light as possibile, it would be nice if I could leave Spring-MVC out.
Apart from that, my biggest issue is about token handling, and particularly about dealing with the steps that lead a user to access an OAuth protected area. From what I got to understand, trying to access a protected area automatically triggers the token generation process, starting from the creation of the unauthorized request token. Unfortunately, this workflow doesn't fit my needs as the scenario I have to deal with involves a user which is already in possess of an authorized access token, and only needs to provide it in order to be granted access to a protected resource. Would it be possibile to override the token generation mechanism with a token retrieval (from a POST/GET for instance) and verification process?
Thank you very much for your effort.
EDIT: (trying to explain things more clearly)
Assume this is the part in my XML where I describe my resource:
<oauth:resource id="OAuthExperimentsRestrictedArea"
key="thisIsExactlyTheConsumerKey"
secret="...andThisIsExactlyTheSecret"
request-token-url="http://localhost:8080/OauthExperiments/oauth/request_token"
user-authorization-url="http://localhost:8080/OauthExperiments/oauth/confirm_access"
access-token-url="http://localhost:8080/OauthExperiments/oauth/access_token" />
What I can't really get to understand is how or where should I pass an already valid access token in case I had it. By trying to directly access the resource via a simple direct link not providing any token, my application would begin the token creation process redirecting me first to request-token-url, next to user-authorization-url and finally to access-token-url. What I need to achieve is the possibility to skip this when I already have a valid token, but what I'm missing is how to do that, where to pass the token (is there a default bean for that? should I pass it as a parameter with a particular name?).
My goal is to have the possibility to delegate even external services for token verification, so what I'm ultimately trying to find is some kind of hook for such procedure. I hope I've explained the whole scenario clearly enough.
That's 2 questions?
Spring MVC is not needed for securing a resource (it's all Spring Security via Servlet Filters).
The second question is about what to do if you have a valid access token and as a consumer you want to send valid requests and access protected resources. A new token would not need to be generated if the request is already authorized.
The answer to the second question is that you need to populate the OAuthSecurityContext (via a thread local managed by OAuthSecurityContextHolder). Obviously you need to be careful to clear it when you are finished. Normally this context is populated by a filter (OAuthConsumerContextFilter) so you can see how that manages the context and copy it. I can't say I like this model much, but that's the way it was implemented (the OAuth2 implementation changed quite a while ago, before 1.0).
In play framework 2, the zentasks sample shows how to do basic authentication. They subclassed Security.Authenticator and added additional methods for authorization. I find it a bit messy, since each method needs to be wrapped with an if-statement.
How can I convert the methods isOwnerOf and isMemberOf into Actions? This would allow me to simply annotate the methods. Currently, I am struggling in create an annotation that would accept the param of the method. Even if I annotate the parameter, then I do not know how to fetch it when the Action is called.
If there's a better way, I would be glad to hear so.
Take a ready to use full stack for authentication/authorization - Play Authenticate
it includes Deadbolt
it offers common providers like Facebook, Twitter, Goolge, etc
it offers common password + own providers
it supports multilanguage (also in informational mails)
it includes ready-to-use Java sample