Multi-Factor Authentication - Part 1
This post is cross posted on Bloom Health’s blog
Two-Factor authentication is a form of authentication which requires the user to confirm their identity by more than just a username and password. There are three types authentication factors from which two must be used. The factors are knowledge (username/password), possession (sending a text message to a phone) and inheritance (fingerprint). This type of authentication has recently become more popular thanks to Google, Twitter and Facebook all adopting multi-factor authentication as an option. If you don’t have this enabled for your accounts, please stop reading this and enable it before you do anything else.
I started writing this post before the Heartbleed SSL vulnerability announced last week. I’m hoping that will bring more awareness and attention to multi-factor or passwordless authentication. Multi-factor authentication isn’t just for Google, if you deal with personally identifiable information then you should be trying to make your user’s data as secure as possible. Luckily, creating a two-factor authentication process with grails and spring security isn’t terribly difficult.
This is going to be the first of a two part series. All of the code can be seen on github of course. I will tag each version as it gets updated for the next blog post. The code is currently tagged as ‘step1’.
The first factor in this example is a knowledge factor requiring the user to know a username and password. The second factor, which will be in Part 2 of this series, will be a possession factor. It will use the Twilio api to send a text message with a one-time use token. The user will provide this token and then be fully authenticated.
Overview of solution
Spring Security uses Authentication Filters and Authentication Providers to do most of the heavy lifting.
- The first step of authentication will use the existing
DaoAuthenticationProviderto verify the user’s username and password.
- Then the user will be given a temporary role which only gives access to a single page.
- The user will be prompted to enter a security token that was sent via text message.
- Then there will be a custom
SecurityTokenAuthenticationProviderwhich will verify the security token.
- After this second step in the authentication process is completed successfully, the user will be granted their roles from the the database.
NB: There are probably multiple ways to do this with Spring Security. This is how we did with a legacy application that had many existing users and roles already.
The first step is to generate the spring-security scaffolding using
grails grails s2-quickstart org.kyleboon User Role. Then I added a dummy user in the bootstrap just for demonstration purposes. You can log in to the example application with user1/password1.
I created a simple HomeController that is protected by default. I pointed the root url to that HomeController.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
You should be able to start the application and log in and be directed to the HomeController index action.
What we want is to force the user to a secondary login page after a successful username and password authentication. To accomplish this, there is a new Role called “ROLE_STEP_ONE_AUTHENTICATED”. Then I created a custom UserDetailsProvider bean that will override the roles coming from GORM and give the UserDetails object a single role.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
And then wire this to the
daoAuthenticationProvider bean that the Grails Spring Security plugin uses by default.
1 2 3 4
Now after logging in, every page will redirect you to the
LoginController.denied() controller method. Finally, have the denied controller method redirect to a new page that will handle the second step of the authentication process. Tracing the controller actions will give something like this:
1 2 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
And create a GSP for step two.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
That’s it for part one of two-factor authentication. At this point if user1 logs in, every page will redirect to the step two authentication page. In the next part of this blog series we’ll complete step two and add the Twilio API for text messaging a security code to the end user.