Preamble
I'm designing an API gateway for a Grails microservice federation. This issue seems related to a bunch of issues already filed in this repository but nothing provides a solution.
Versions and Configurations
Grails: 3.2.2
Tomcat: 8.5
Plugin versions:
compile 'org.grails.plugins:spring-security-core:3.1.2'
compile "org.grails.plugins:spring-security-rest:2.0.0.M2"
I'm using spring security rest plugin for only token authentication. I'm doing the authorization part myself by returning ROLE_NO_ROLES
for all the users in getAuthorities()
. I intercept all the requests and authorize the access based on my own authorization schema stored in DB.
Problem:
With these configurations and strategy, my code works as desired when I run it on my local system. When I deploy it on a server as a war file in tomcat, it works fine for all the requests to the gateway, i.e., for all requests of the pattern /umm/controller/action
. Spring security context is there and the user is evaluated perfectly.
When I try to call other microservices by redirection with requests of the form /umm/microservice/controller/action
, springSecurityService.getCurrentUser()
and springSecurityService?.principal?.username
start to return null. Although my token gets evaluated perfectly, yet I'm not getting any security context.
For details, have a look on this issue. The details for reproducing the bug are also provided in the aforementioned issue. The whole project is available here.
Update: May 19, 2017
I tried deploying my war in a Tomcat on my local machine. This question and this question provide following solutions.
- disabling tomcat cache
- setting
grails.plugin.springsecurity.sch.strategyName = org.springframework.security.core.context.SecurityContextHolder.MODE_INHERITABLETHREADLOCAL
Nothing seems to work so far. SecurityContextHolder
is returning null
anyway. All the user retrieving functions of SpringSecurityService
viz. getCurrentUser()
, getPrincipal()
, getAuthentication()
and loadCurrentUser()
return null.
Update: May 23, 2017
To narrow down the problem, I executed the standalone war using
java -Dgrails.env=prod -jar build/libs/mywar-0.1.war
Now for any non-umm request, I get a 404, page not found
. I think the problem is with the production environment. The app works completely fine in the development.
Also tried grails run-app
which works fine. To rule out the problem with the production environment, I created the war using grails dev war
but to no avail. Nothing works so far for the war
.
Update: May 25, 2017
I should probably ask this http://security.stackexchange.com but for the record, I'm asking it here too.
The answer provided by me below contains a workaround fix. The mechanism by which the fix works is explained in the answer. My question is:
- Does this approach introduce any vulnerability or loophole in the security system?
- Is this authorization schema safe or needs to be revised?
- I'm authenticating through the plugin but authorizing myself. Can somebody bypass the security filters and hit the authorization interceptor directly? Because if someone can do that, he will only have to give me an admin's username in the same format as the token does and he'll have access to everything.