SpringSecurityService.principal returns Null when deployed as a WAR in tomcat 8.5

Preamble

I am designing an API gateway for the Grails microservice federation. This problem seems to be related to a bunch of problems already filed in this repository , but nothing gives a solution.

Versions and Configurations

Grails: 3.2.2

Tomcat: 8.5

Plugin version:

compile 'org.grails.plugins:spring-security-core:3.1.2' compile "org.grails.plugins:spring-security-rest:2.0.0.M2" 

I use spring security plugin to check only token. I do the authorization part myself, returning ROLE_NO_ROLES for all users in getAuthorities() . I intercept all requests and allow access based on my own authorization scheme stored in the database.

Problem:

With these configurations and strategies, my code works as needed when I run it on my local system. When I deploy it to the server as a war file in tomcat, it works fine for all requests to the gateway, i.e. For all requests of the template /umm/controller/action . spring there is a security context, and the user is well rated.

When I try to call other microservices by redirecting with requests of the form /umm/microservice/controller/action , springSecurityService.getCurrentUser() and springSecurityService?.principal?.username , it will return null. Although my token is rated excellent, I am not getting any security context.

See issue for more details . Details for reproducing the error are also indicated in the above problem. The whole project is available here .

Update: May 19, 2017

I tried to deploy my war on Tomcat on my local machine. This question and question provides the following solutions.

  • disable tomcat cache
  • setting grails.plugin.springsecurity.sch.strategyName = org.springframework.security.core.context.SecurityContextHolder.MODE_INHERITABLETHREADLOCAL

Nothing is working yet. SecurityContextHolder returns null anyway. All custom SpringSecurityService return functions, namely. getCurrentUser() , getPrincipal() , getAuthentication() and loadCurrentUser() returns null.

Update: May 23, 2017

To narrow down the problem, I carried out an offline war using

 java -Dgrails.env=prod -jar build/libs/mywar-0.1.war 

Now for any request other than umm, I get 404, page not found . I think the problem is with the production environment . The application works great in development.

Also tried grails run-app , which works great. To eliminate the problem with the production environment, I created a war using grails dev war , but to no avail. So far, nothing is working for war .

Update: May 25, 2017

I should probably ask this http://security.stackexchange.com , but for the record I also ask for it here.

The answer below provides a fix to the workaround. The mechanism by which the fix works is explained in the answer. My question is:

  • Does this approach provide any security vulnerability or loophole?
  • Is this authorization scheme secure or needs to be reviewed?
  • I authenticate through the plugin but allow myself. Can someone bypass the security filters and directly get into the authorization interceptor? Because if someone can do this, he will need to give me the administrator name in the same format as the token, and he will have access to everything.
+7
spring-security tomcat8 grails3 spring-security-rest
source share
1 answer

Bypass

I have a workaround for the problem. Since I needed only the username, I grabbed the rest of the token in my interceptor, decrypted it, and extracted the username from it.

Here:

 def extractUsername(def token){ Base64 coder = new Base64() def tok = token - "Bearer " def principal = tok.tokenize(".") def dec = coder.decode(principal[1]) def sub = new String(dec) def user = sub.tokenize(",") def username=user[1].tokenize(":") username = username[1]-"\"" return username-"\"" } 

This worked for me because I did not have to check the springSecurityService.Principal object. If that were the case, I would not be able to get the username. springSecurityService.Principal and springSecurityService.getCurrentUser() still return null. The problem has not yet been resolved. I answer because I did not have a single comment, despite the generosity. The answer to the original question is still welcome if anyone can explain why spring-security-plugin behaves this way .

Edit: May 25, 2017

The workaround I used is based on the structure of the token and the fact that the username is embedded in the token and the token is simply base64 encoded.

This is the original token created by spring's REST security plugin for grails:

eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0RrRkJpbWdCcVpVNjBLVjBxeHlKanBsSVNwRXFLNmthc2xDcDZHSVwvM0lQem5iazdrMlNwTXBXQkFVU0xWSld2d0RlQmhROVF0VU5YNXE1OVp3aE91eUJ1c2ZYdTU5K1wvNTdNcm1EWWFYc2FhY1dIOFZHUXhsNzVKTlpleHdURFQzQTc5ektDTzBPYUl0UnpZcFFsY0g2OEVYZ0FsSGxsWUNMYlpIcXNKSnVOYXU3ZU5vYTBQTkN3ckhkOHdibW1XWUZcL3BIZitXTzFRYVwveEVvcUwzdkphaHN3RHdMUTVWSjIxSnlkWkJ5amRFR3pCV3pRSVU3YnZRb3BCdVVsak5oSnFFVmxLd25NQXFneWpMN1VaRXFSMlBoNGJYWnpISlI2NkN0QnpDVE1tUEkzWDlKT3RaWmRcL2ZPcHFRRXVcL0FKeW9QVW8wUGRQWGRRM1wvSDRUU1VFcGVaS21xV3VURlRFdDdnVEpcLzdSNHZIbDRlbW9Xd0tnVGw3Y1wvVTB4ZjlLQTBmbUhQMFwvem9yM1F3dU1KNndXc1Brakp6WHpCdks3UktmXC80OXZiTHlkWCsreWxTZG9qWDk5XC9IMHNwTmM4T21TbEttbVZVVE95TGFmdG05RTNuamJ2THhGb1oraHllcFFQcWpwTVhvVnFJZ3ByaGxyY1M0Ynd1ejc5ckI2bWFydmVtZUhUZXBzQ2poOGxXRHBCXC9reWQzS1wvRURSd2c1K0gxMGNQdnRKTkc5Z2VvK0pES240dVFMVXlwSWU2czluSjR2VnI3OE84aGpqWFwvb3Z4RG9UU3hZREFBQT0iLCJzdWIiOiJhZG1pbkRCIiwicm9sZXMiOlsiUk9MRV9OT19ST0xFUyJdLCJleHAiOjE0OTU3MTU3OTMsImlhdCI6MTQ5NTcx Mj E5M30.MPEXURGhJo5s75LfUSm5ckG99Byc7FCLyj1gYZJu1zk

This is the decrypted version:

"Chief": "H4sIAAAAAAAAAJVSP0 / bQBR / DkFBimgBqZU60KV0qxyJjplISpEqK6kaslCp6GI / 3IPznbk7k2SpMpWBAUSLVJWvwDeBhQ9QtUNX5q59ZwhOuyBusfXu59 + / 57MrmDYaXsaacWH8VGQxl75JNZexwTDT3A79zKCO0OaItRzYpQlcH68EXgAlHllYCLbZHqsJJuNau7eNoa0PNCwrHd8wbmmWYF / PHF + WO1Qa / xEoqL3vJahswDwLQ5VJ21JydZByjdEGzBWzQIU7bvQopBuUljNhJqEVlKwnMAqgyjL7UZEqR2Ph4bXZzHJR66CtBzCTMmPI3X9JOtZZd / fOpqQEu / AJyoPUo0PdPXdQ3 / H4TSUEpeZKmqWuTFTEt7gTJ / 7R4vHl4emoWwKgTl7c / U0xf9KA0fmHP0 / zor3QwuMJ6wWsPkjJzXzBvK7RKf / 49vbLydX ++ ylSdojX99 / H0spNc8OmSlKmmVUTOyLaftm9E3njbvLxFoZ + hyepQPqjpMXoVqIgprhlrcS4bwuz79rB6marvemeHTepsCjh8lWDpB / kyd3K / EDRwg5 + H10cPvtJNG9geo + JDKn4uQLUypIe6s9nJ4vVr78O8hjjX / ovxDoTSxYDAAA = ", " sub ":" adminDB " ," roles ": [" ROLE_NO_ROLES "]," Exp ": 1495715793," IAT ": 1495712193

The principle of operation here is signed and encrypted, but the username is not encrypted. Therefore, it can be easily extracted from the above code.

+1
source share

All Articles