Spring Security

Introduction to Spring Security – The Architecture and Design – Part 2

OK, took me a bit longer to get to this post that I wanted. I am also going to make this public before it is 100% complete. So stay tuned I might be updating this with more information as time goes by.

In Part 1 on this Spring Security series I talked about the goals of Spring Security and started covering the design of the Authentication pieces of Spring Security. In Part 2 we will talk about the design of the Authorization pieces of Spring Security. In Part 3 we will talk about setting up Spring Security and the basic configuration that you need to do to secure Web URLs and Method security.

So Authorization is a bit more complex because there are many decisions to be made about the granularity of your security authorization. Meaning are secured resources going to be accessible to members of a GROUP, high coarse grained authorization. Or ROLE based which is a little bit less coarse, but still easy to maintain users to roles, just like groups. Or you could be more fine grained using ACLs, permissions that determine what a user can do. Or even more fine grained down to specific rows of data that a user can see.

And Spring Security needs to be able to provide all those granularities while still having a simple consistent, extensible, flexible approach. Now that is a tough thing to do, but I think that Spring Security did an exceptional job at it.

So, for a high level talk about the components and design of authorization in Spring Security, we are only going to look at one simple solution (Yes, I am taking the easy way out). In our article today, we will take the ROLE based approach to authorization. Where we say a user must be a member of ROLE_USER or ROLE_ADMIN in order to see the Account edit page on a website. Or maybe to call a particular method.

So after we have been authenticated and we want to access some secured resource. Say a URL, or a method we need something to check to see if the current user has some groups, role, or permission that is needed for that resource. Typically it is easy to do Role based decisions here. So we have information of what role you need to access the resource as well as the current users roles (Stored in their UserDetails, which talked about in the last article)

So now we need someone to compare the two. So the incoming Thread call is intercepted and the information is passed to an object calls an AccessDecisionManager. OH BOY! Another Manager. Just what we always needed. Someone who does nothing but delegate. And does it delegate. It delegates to a Collection of objects called AccessDecisionVoter(s). A Voter is nothing more than a method in the AccessDecisionVoter interface that returns an int. Yay (positive number), Nay(negative number) or Abstain(0 is returned). So it the responsibility of a Voter to vote on whether the user should have access to the resource. We should say there are a couple of supports() methods that tell the AccessDecisionManager what types of decisions they support and should be called upon. (Basically, not all voters vote. If a Group is passed in for the check, why should a Role Based voter even vote.)

For something like Role Based security, the Voter is given the resource settings as well as the current Thread’s User and compares the Roles the user has against what is needed for the resource. If they have a match, then great Yay is voted. The Voter returns a positive integer. If they want to vote No, then they return a negative number.

As a matter of fact in basic environments of Spring Security with things like it gives you a RoleVoter. You should check out that class sometime. It is interesting. Like it has a prefix property that by default is set to “ROLE_”. Which means that if your data store of users that is storing what roles users have and they aren’t all starting with “ROLE_” like ROLE_USER or ROLE_ADMIN, then watch out, you might spend three days trying to figure out why you can’t get access to a page that you know your user has the correct role for. If it is stored as USER and you do your Spring Security with access=”USER” IT WILL NOT WORK!. It would have to have access=”ROLE_USER” and what ever when you get your user data from the data store that you append “ROLE_” to the front. OR better yet you change the prefix property (Which if fun to go and find. HINT: the security:jdbc-xxxx has an attribute for prefix)

OK, anyway. You have these voters voting on whether to allow the user through to the resource. Here is where things get fun. You can have a whole collection of Voters, each voting. So we might have a count of how many returned positive YAY numbers and set it such that all of the voters have to say YAY or you don’t get though. Or make it a majority (Not sure what happens if you have an even number of Voters), or just one needs to say YAY to let you through.

Pretty cool. I have found about 8 different voter implementation in Spring Security. But you could also write your own.

Introduction to Spring Security – The Architecture and Design – Part 1

In this multi part article I am going to explain the key components/classes/interfaces that make up Spring Security architecture and design. By understanding these components, we will be able to show in future articles how to customize Spring Security with simply implementing an interface and configuring it as a Spring bean.

The main thing to understand about Spring Security is that it is broken down to many little parts or interfaces for each piece of the security solution. Each part is responsible for just a small portion of the big security picture. So instead of having just a couple of classes to handle everything, which would be less flexible, less customizable, low cohesion and tightly coupled, we have an architecture that is based on many interfaces, such that we can swap out implementations with either built in components or our own custom implementations, at will, without affecting other parts of your security solution and your application.

But this means that you need to know all of these interfaces/classes and what role/responsibility each one has. You also must know how much of a security solution you need. Do you want coarse or fine grained authorization, from group-based to role-based or down to fine grained access control lists based on application data? Do you just need authentication but not authorization?

You might also ask, where do you store your user information for authentication and authorization? is it in a database, LDAP, Active Directory? Do you need encryption? What type of encryption? What are you securing? Is it just a URL for a web page, or is it parts of a web page? Is it JMS Messaging or SOAP Web Services that need to be secured? How about all your code should your methods being secured too? These are many of the factors that will determine what parts of Spring Security you need to use.

Great now that I have completely confused you, let me confuse you some more! This is why I need at least a two part article to cover many of these components. This first part will be on Authentication and the second part will be on Authorization.

First we will talk about a user. This is a username and password as well as some type of authorization information. In Spring Security we have an interface called a UserDetails to store that information. A UserDetails implementation will store a String for the username as well as a String for the password, and it will have a collection of objects called GrantedAuthority. A GrantedAuthority object is just a holder class to hold a String for each role that the UserDetails/user has. So if I have a user Bob who has ROLE_ADMIN and ROLE_USER assigned to them in a database, then Bob’s UserDetails instance will have two GrantedAuthority instances in its collection. There are a couple of other boolean properties that also need to be set with the UserDetails interface, one of these for instance is used to say whether the user is still active or enabled.

Now that we have an object to hold all the user information, UserDetails. How do we one created? How do we have someone log in and have Spring look up the user information, check that the enter their correct credentials and then have a UserDetails object instantiated and holding that user’s information? That is the role of authentication. And in Spring the main class responsible for controlling authorization is an interface called AuthenticationManager. It is a manager, so like all manager’s we know, it just delegates to others to do the actual work.

So what do we have to do here? There are really just two parts. 1) look up the user information and populate the UserDetails object with that information and 2) Check that the password matches. (there are other authenication mechanisms like certificates which are exactly user/password checking, but for simplicity right now we will ignore those scenarios)

If anything fails in these two steps, Spring Security will throw exceptions. If it is successful, then Spring Security will take the UserDetails object and store it somewhere so that we don’t have keep looking up that information again and again while the user is logged in.

Who does the AuthenticationManager delegate to? It will delegate to a collection of AuthenticationProvider instances. An AuthenticationProvider is an interface that maps to a data store which stores your user data. Based on the type of data store a query of some type must be used to get the data for the user.

For that part, an AuthenticationProvider will call an object that implements the UserDetailsService interface. A UserDetailsService looks up the user data and returns a UserDetails object fully populated. If the UserDetailsService cannot find this user then a UsernameNotFoundException is thrown. Why username not found? Because the UserDetailsService interface has just one method loadUserByUsername(String username). So when we go to our data store and query it, the only information we have is the String username to run our queries with.

Once the UserDetailsService returns a UserDetails object, then the AuthenticationProvider will check that the password matches the password the user entered. If it does not match, then the AuthenticationProvider will throw an AuthenticationException, or a subclass of it like BadCredentialsException. Thrown because the password or credentials that the user entered in the login screen were incorrect.

So the process goes something like this. A user enters their username and password into a login screen and clicks a login button. The entered information is placed into an object called Authentiation which is passed to the AuthenticationManager’s authenticate method. this method will loop through all AuthenticationProviders that are configured and calls their authenticate method, passing in the Authentication object. Each AuthenticationProvider will calls its configured UserDetailsService’s loadUserByUserName method.

In most applications, the configuration to set all this up is pretty easy. As a matter of fact, you can pretty much get all of it with just one tag from the security xml namespace. However, what will always be different with all your applications. That will be where and how you store your user data. Spring will not be able to predict that, so the configuration that you must do is to tell Spring Security what UserDetailsService do you want to use and assign it to an AuthenticationProvider.

In the next article (soon I promise), we are going to look at all the Authentication interfaces and configuration in detail.