The problem and lead up to the solution
I have been working on an authentication issue for more than a month. This has been incredibly irritating, and I have not found anything related to this online – not even in Stack Overflow questions. The issue is that I followed the instructions for installing Spring Security, Spring Security OAuth, and the Google [etc] plugins for my existing application. After following the instructions to a T, I clicked on the authentication button for the Google OAuth. What happened? I was sent right back to the login screen.
This was rather weird. My first few thoughts were:
- Did the authentication fail?
After an investigation, found this to be false. Chrome’s developer tools showed that the network path redirected to the /oauth/callback and then to /oauth/google/success. So that was a no.
- Was the redirection page not working?
I really had no idea on this. It seemed to work for the locked-down resources. But I still seemed to have received the login page after coming back from Google OAuth. That’s logged within the Spring Security plugin depths.
- Was the authentication return point getting rejected?
Here we would have a loop back to the authentication page.
- What controllers were getting hit?
The debugger won’t go into the controller call itself. Also, the expected controller wasn’t getting hit. So this wasn’t of any help.
- Were the Plugins incompatible with my Grails 2.4.3 application?
I was using the most up to date plugins for Spring Security. (The most recent publication date of May 2014 didn’t help with this concern)
After these thoughts, I was stuck. There were other scenarios on Stack Overflow and mailing lists that made claims to the plugin not working. However, most of those issues were resolved by switching plugins or due to syntax errors in the config. Additionally, I checked the plugins’ issue pages and there was apparently nothing about the issue I was having.
To answer the third idea of where the problem could be, I looked over the following static set of rules configured in the config:
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
‘/’ : [‘permitAll’],
‘/index’ : [‘permitAll’],
‘/index.gsp’ : [‘permitAll’],
‘/assets/**’ : [‘permitAll’],
‘/**/js/**’ : [‘permitAll’],
‘/login/auth’ : [‘permitAll’],
‘/**/css/**’ : [‘permitAll’],
‘/**/images/**’ : [‘permitAll’],
‘/oauth/**’ : [‘permitAll’]
After all the addition of the login/oauth bits were recommended in the documentation.
I even tried testing Google’s side with the console. Everything worked on their end. My assumption was that if one of the plugins was misconfigured it would try to alert me via the logs. (Well, as I learned that assumption made an ass of me.) Finally I did some research within the plugin. I found the package structure in which I could bring in the logs.
That eventually lead me to a lot of logging about only the filters/interception of web traffic, which didn’t help very much, and it still lead me to question what was going on. So I tried logging the service and controller methods. (That lead me to realize that I was never getting the actual OAuth plugin to kick back in on the way back. Additionally I found this bit in the logs (that were enabled earlier):
intercept.AnnotationFilterInvocationDefinition no config for ‘/springsecurityoauth/onsuccess’ (which was followed by a redirect to /login/auth.)
Google was not much of a help for this method. Nor was it a lot of help for the ‘springsecurityoauth/onsuccess’ path. This meant that the access to the actual controller SpringSecurityOAuth::onsuccess method couldn’t be reached. This was a bit confusing since the Spring Seucrity OAuth defines it’s own URL mappings in: SpringSecurityOauthUrlMappings. Alas, it’s a static call. I’m not able to debug that low.
This led to another path: Well how are the other path’s defined, and why isn’t /springSecurityOAuth/onSuccess allowed. SpringSecurityOauthUrlMappings maps the controller to /oauth/$provider/success, and that’s allowed under my rules.
Well that path isn’t allowed. Why? Spring Security has 2 ways to lock down your application.
- InterceptUrlMap Method: Statically define all of your paths/roles via a static map in the config.
- Controller Annotations Method: This allows for you to define some static rules requests are allowed and to what accounts in the config file. It also allows for you annotate your controllers/methods to what is allowed by what role(s).
Guess which way I went. Yep, I went the progressive route and chose the controller annotations method. That worked really well for what I had, and with authentication outside of this plugin. But it failed when trying to return. Why did this still fail? Well the configuration of springsecurity.controlelerAnnotation.staticRules = [ …. ] was missing the reference to the controller (that looks like a url): ‘/springSecurityOAuth/**’: [‘permitAll’]
After adding that small change: everything worked. A lot of time was lost. I’m going to need a break away from Spring Security. That and probably quite a few drinks.
What could have been improved?
The documentation needs to be updated to mention controller annotations.