grails / grails-spring-security-core

Grails Spring Security Core Plugin
Apache License 2.0
259 stars 222 forks source link

springSecurityService.principal returns Null when deployed as a WAR in tomcat 8.5 #490

Open saqib-ahmed opened 7 years ago

saqib-ahmed commented 7 years ago

Task List

Preamble

I'm designing an API gateway for a grails microservice federation. This issue seems related to a bunch of issues already filed. The closest issue is #482 (not exactly same). But I'm still unable to get around despite trying various suggestions. This question also gives a close problem but not the same.

Versions and Configurations

Grails: 3.2.2

Tomcat: 8.5

Application Name: umm

I'm using following plugin versions:

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

Security configuration is as follows:

grails.plugin.springsecurity.sch.strategyName = org.springframework.security.core.context.SecurityContextHolder.MODE_INHERITABLETHREADLOCAL
grails.plugin.springsecurity.interceptUrlMap = [
        [pattern: '/',               access: ['permitAll']],
        [pattern: '/error',          access: ['permitAll']],
        [pattern: '/index',          access: ['permitAll']],
        [pattern: '/index.gsp',      access: ['permitAll']],
        [pattern: '/shutdown',       access: ['permitAll']],
        [pattern: '/assets/**',      access: ['permitAll']],
        [pattern: '/**/js/**',       access: ['permitAll']],
        [pattern: '/**/css/**',      access: ['permitAll']],
        [pattern: '/**/images/**',   access: ['permitAll']],
        [pattern: '/**/favicon.ico', access: ['permitAll']],
        [pattern: '/login',          access: ['permitAll']],
        [pattern: '/login/**',       access: ['permitAll']],
        [pattern: '/logout',         access: ['permitAll']],
        [pattern: '/logout/**',      access: ['permitAll']],
        [pattern: '/console/**',     access: ["hasIpAddress(\'127.0.0.1\') || hasIpAddress(\'::1\')"]],
        [pattern: '/static/console/**', access: ["hasIpAddress(\'127.0.0.1\') || hasIpAddress(\'::1\')"]],
        [pattern: '/**',             access: ['ROLE_NO_ROLES']]
]

grails.plugin.springsecurity.filterChain.chainMap = [
        [pattern: '/assets/**',      filters: 'none'],
        [pattern: '/**/js/**',       filters: 'none'],
        [pattern: '/**/css/**',      filters: 'none'],
        [pattern: '/**/images/**',   filters: 'none'],
        [pattern: '/**/favicon.ico', filters: 'none'],
        [pattern: '/console/**',     filters: 'none'],
        [pattern: '/static/console/**', filters: 'none'],
        [pattern: '/**',             filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,' +
                                    '-exceptionTranslationFilter,-authenticationProcessingFilter,' +
                                    '-securityContextPersistenceFilter,-rememberMeAuthenticationFilter']
]

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. before() method of my interceptor looks like following:

...
        (microName, controller, action) = authorizationService.extractURI(request.forwardURI)

        log.info("Requested URI is: " + request.forwardURI)
        log.info("Name of the microservice is: " + microName)
        log.info("Name of the controller is: " + controller)
        log.info("Name of the action is: " + action)
        log.info("Logged in user is " + springSecurityService.getCurrentUser())

        micro = Microservice.findByName(microName)

        if(microName != "umm"){
            log.info("If authorized, request will be forwarded to: ${micro?.ipAddress}${req}")
        }

        if(!springSecurityService?.principal?.username){
            log.info("Access denied. Token not provided in the header.")
            resultSet.put("message", "Access denied. Token not provided in the header.")
            response.status = 403
            render resultSet as JSON
            return false
        }
...

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.

Following is the output for a failure case:

DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request '/pcsbackend/settings/getAllPromptFiles' matched by universal pattern '/**'
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles at position 1 of 7 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles at position 2 of 7 in additional filter chain; firing Filter: 'MutableLogoutFilter'
DEBUG org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/pcsbackend/settings/getAllPromptFiles'; against '/logoff'
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles at position 3 of 7 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
DEBUG grails.plugin.springsecurity.rest.RestAuthenticationFilter - Actual URI is /pcsbackend/settings/getAllPromptFiles; endpoint URL is /api/login
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles at position 4 of 7 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles at position 5 of 7 in additional filter chain; firing Filter: 'RestTokenValidationFilter'
DEBUG grails.plugin.springsecurity.rest.token.bearer.BearerTokenReader - Looking for bearer token in Authorization header, query string or Form-Encoded body parameter
DEBUG grails.plugin.springsecurity.rest.token.bearer.BearerTokenReader - Found bearer token in Authorization header
DEBUG grails.plugin.springsecurity.rest.token.bearer.BearerTokenReader - Token: eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0RvbEFRbENvVkNRR3VoUzJ5cEhhTVZOQmdJU3NwR3FhQlNUUXhYNjRCK2M3OSs0TXlZSXl3Y0FBb2tXcTJxXC9BTjRHRkQxQ1ZnWldabFhlRzRNQ0Nlb3V0ZHpcL1wvXC9qMmYzVURGYVBnWWE4YUY4Vk9SeFZ6Nkp0VmN4Z2JEVEhQYjlUT0RPa0tiSTVaellJc21jSCs4RW5nQmxIaGs0WFd3eFhaWVZUQVpWeHZ0TFF4dHJhUGhnOUx4QStPbVpnbnVLcjN0UDNLSFN1TVRnWUxhKzEyQzRWV1laR0dvTW1uclNpNTJVcTR4V29XSlloYW9jTnVOM29SMGc5SnlKc3dnZEJnbGF3dU1BaGhsbWYybVNKV2pzZkRxM214bXVhZzIwZFlDR0VtWk1lVHVXWkttZGRiZHZiTXBLY0YzMklOeUpcL1hvVUhkekR1bzdIbjlCQ1VHcHVaSm10aVVURmZGTjdzU0p2emR6Y25uMHA5Y3FBVkFuNzFcLytwcGhQejBQdmZQMzJiVjYwRjFxWUdyQmV3R3FkbE54TUZzeGZOVHJsdjc4K1wvemk5T1ZnYkltV0hXUHJcL2ZjeCtlbWl1dTZDU2xHbG0xY0NPaUhhMzdONkpmUDVsOHY0V3VuNlRKNmxBK3FPa3hlaFJvaUNtdUdXdFJMOXZDMk5mR3NIaVJyMng0WjVOTjZtd0tPR1NoTWZ6M0c1aGZxQm9YWWZYeHhkSDdcLzRSeVFwVWRwaklrR3FmS0VEMUxHbWozajg3blJuOWVYV1loK2pcLzBIZG0rVnVGRkFNQUFBPT0iLCJzdWIiOiJhZG1pbiIsInJvbGVzIjpbIlJPTEVfTk9fUk9MRVMiXSwiZXhwIjoxNDk0OTI5MDE1LCJpYXQiOjE0OTQ5MjU0MTV9.R_UIO2sQ6Q6gPBPIcypQJRawHJroLPyxbKbUSNQfQLE
DEBUG grails.plugin.springsecurity.rest.RestTokenValidationFilter - Token found: eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0RvbEFRbENvVkNRR3VoUzJ5cEhhTVZOQmdJU3NwR3FhQlNUUXhYNjRCK2M3OSs0TXlZSXl3Y0FBb2tXcTJxXC9BTjRHRkQxQ1ZnWldabFhlRzRNQ0Nlb3V0ZHpcL1wvXC9qMmYzVURGYVBnWWE4YUY4Vk9SeFZ6Nkp0VmN4Z2JEVEhQYjlUT0RPa0tiSTVaellJc21jSCs4RW5nQmxIaGs0WFd3eFhaWVZUQVpWeHZ0TFF4dHJhUGhnOUx4QStPbVpnbnVLcjN0UDNLSFN1TVRnWUxhKzEyQzRWV1laR0dvTW1uclNpNTJVcTR4V29XSlloYW9jTnVOM29SMGc5SnlKc3dnZEJnbGF3dU1BaGhsbWYybVNKV2pzZkRxM214bXVhZzIwZFlDR0VtWk1lVHVXWkttZGRiZHZiTXBLY0YzMklOeUpcL1hvVUhkekR1bzdIbjlCQ1VHcHVaSm10aVVURmZGTjdzU0p2emR6Y25uMHA5Y3FBVkFuNzFcLytwcGhQejBQdmZQMzJiVjYwRjFxWUdyQmV3R3FkbE54TUZzeGZOVHJsdjc4K1wvemk5T1ZnYkltV0hXUHJcL2ZjeCtlbWl1dTZDU2xHbG0xY0NPaUhhMzdONkpmUDVsOHY0V3VuNlRKNmxBK3FPa3hlaFJvaUNtdUdXdFJMOXZDMk5mR3NIaVJyMng0WjVOTjZtd0tPR1NoTWZ6M0c1aGZxQm9YWWZYeHhkSDdcLzRSeVFwVWRwaklrR3FmS0VEMUxHbWozajg3blJuOWVYV1loK2pcLzBIZG0rVnVGRkFNQUFBPT0iLCJzdWIiOiJhZG1pbiIsInJvbGVzIjpbIlJPTEVfTk9fUk9MRVMiXSwiZXhwIjoxNDk0OTI5MDE1LCJpYXQiOjE0OTQ5MjU0MTV9.R_UIO2sQ6Q6gPBPIcypQJRawHJroLPyxbKbUSNQfQLE
DEBUG grails.plugin.springsecurity.rest.RestTokenValidationFilter - Trying to authenticate the token
DEBUG grails.plugin.springsecurity.rest.RestAuthenticationProvider - Use JWT: true
DEBUG grails.plugin.springsecurity.rest.RestAuthenticationProvider - Trying to validate token eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0RvbEFRbENvVkNRR3VoUzJ5cEhhTVZOQmdJU3NwR3FhQlNUUXhYNjRCK2M3OSs0TXlZSXl3Y0FBb2tXcTJxXC9BTjRHRkQxQ1ZnWldabFhlRzRNQ0Nlb3V0ZHpcL1wvXC9qMmYzVURGYVBnWWE4YUY4Vk9SeFZ6Nkp0VmN4Z2JEVEhQYjlUT0RPa0tiSTVaellJc21jSCs4RW5nQmxIaGs0WFd3eFhaWVZUQVpWeHZ0TFF4dHJhUGhnOUx4QStPbVpnbnVLcjN0UDNLSFN1TVRnWUxhKzEyQzRWV1laR0dvTW1uclNpNTJVcTR4V29XSlloYW9jTnVOM29SMGc5SnlKc3dnZEJnbGF3dU1BaGhsbWYybVNKV2pzZkRxM214bXVhZzIwZFlDR0VtWk1lVHVXWkttZGRiZHZiTXBLY0YzMklOeUpcL1hvVUhkekR1bzdIbjlCQ1VHcHVaSm10aVVURmZGTjdzU0p2emR6Y25uMHA5Y3FBVkFuNzFcLytwcGhQejBQdmZQMzJiVjYwRjFxWUdyQmV3R3FkbE54TUZzeGZOVHJsdjc4K1wvemk5T1ZnYkltV0hXUHJcL2ZjeCtlbWl1dTZDU2xHbG0xY0NPaUhhMzdONkpmUDVsOHY0V3VuNlRKNmxBK3FPa3hlaFJvaUNtdUdXdFJMOXZDMk5mR3NIaVJyMng0WjVOTjZtd0tPR1NoTWZ6M0c1aGZxQm9YWWZYeHhkSDdcLzRSeVFwVWRwaklrR3FmS0VEMUxHbWozajg3blJuOWVYV1loK2pcLzBIZG0rVnVGRkFNQUFBPT0iLCJzdWIiOiJhZG1pbiIsInJvbGVzIjpbIlJPTEVfTk9fUk9MRVMiXSwiZXhwIjoxNDk0OTI5MDE1LCJpYXQiOjE0OTQ5MjU0MTV9.R_UIO2sQ6Q6gPBPIcypQJRawHJroLPyxbKbUSNQfQLE
DEBUG grails.plugin.springsecurity.rest.token.storage.jwt.JwtTokenStorageService - Successfully verified JWT
DEBUG grails.plugin.springsecurity.rest.token.storage.jwt.JwtTokenStorageService - Trying to deserialize the principal object
DEBUG grails.plugin.springsecurity.rest.token.storage.jwt.JwtTokenStorageService - UserDetails deserialized: grails.plugin.springsecurity.userdetails.GrailsUser@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_NO_ROLES
DEBUG grails.plugin.springsecurity.rest.RestAuthenticationProvider - Now is Tue May 16 14:22:51 PKT 2017 and token expires at Tue May 16 15:03:35 PKT 2017
DEBUG grails.plugin.springsecurity.rest.RestAuthenticationProvider - Expiration: 2443
DEBUG grails.plugin.springsecurity.rest.RestAuthenticationProvider - Authentication result: grails.plugin.springsecurity.rest.token.AccessToken(accessToken:eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0RvbEFRbENvVkNRR3VoUzJ5cEhhTVZOQmdJU3NwR3FhQlNUUXhYNjRCK2M3OSs0TXlZSXl3Y0FBb2tXcTJxXC9BTjRHRkQxQ1ZnWldabFhlRzRNQ0Nlb3V0ZHpcL1wvXC9qMmYzVURGYVBnWWE4YUY4Vk9SeFZ6Nkp0VmN4Z2JEVEhQYjlUT0RPa0tiSTVaellJc21jSCs4RW5nQmxIaGs0WFd3eFhaWVZUQVpWeHZ0TFF4dHJhUGhnOUx4QStPbVpnbnVLcjN0UDNLSFN1TVRnWUxhKzEyQzRWV1laR0dvTW1uclNpNTJVcTR4V29XSlloYW9jTnVOM29SMGc5SnlKc3dnZEJnbGF3dU1BaGhsbWYybVNKV2pzZkRxM214bXVhZzIwZFlDR0VtWk1lVHVXWkttZGRiZHZiTXBLY0YzMklOeUpcL1hvVUhkekR1bzdIbjlCQ1VHcHVaSm10aVVURmZGTjdzU0p2emR6Y25uMHA5Y3FBVkFuNzFcLytwcGhQejBQdmZQMzJiVjYwRjFxWUdyQmV3R3FkbE54TUZzeGZOVHJsdjc4K1wvemk5T1ZnYkltV0hXUHJcL2ZjeCtlbWl1dTZDU2xHbG0xY0NPaUhhMzdONkpmUDVsOHY0V3VuNlRKNmxBK3FPa3hlaFJvaUNtdUdXdFJMOXZDMk5mR3NIaVJyMng0WjVOTjZtd0tPR1NoTWZ6M0c1aGZxQm9YWWZYeHhkSDdcLzRSeVFwVWRwaklrR3FmS0VEMUxHbWozajg3blJuOWVYV1loK2pcLzBIZG0rVnVGRkFNQUFBPT0iLCJzdWIiOiJhZG1pbiIsInJvbGVzIjpbIlJPTEVfTk9fUk9MRVMiXSwiZXhwIjoxNDk0OTI5MDE1LCJpYXQiOjE0OTQ5MjU0MTV9.R_UIO2sQ6Q6gPBPIcypQJRawHJroLPyxbKbUSNQfQLE, expiration:2443, refreshToken:null, principal:grails.plugin.springsecurity.userdetails.GrailsUser@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_NO_ROLES, super:grails.plugin.springsecurity.rest.token.AccessToken@8d3530c3: Principal: grails.plugin.springsecurity.userdetails.GrailsUser@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_NO_ROLES; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_NO_ROLES)
DEBUG grails.plugin.springsecurity.rest.RestTokenValidationFilter - Token authenticated. Storing the authentication result in the security context
DEBUG grails.plugin.springsecurity.rest.RestTokenValidationFilter - Authentication result: grails.plugin.springsecurity.rest.token.AccessToken(accessToken:eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0RvbEFRbENvVkNRR3VoUzJ5cEhhTVZOQmdJU3NwR3FhQlNUUXhYNjRCK2M3OSs0TXlZSXl3Y0FBb2tXcTJxXC9BTjRHRkQxQ1ZnWldabFhlRzRNQ0Nlb3V0ZHpcL1wvXC9qMmYzVURGYVBnWWE4YUY4Vk9SeFZ6Nkp0VmN4Z2JEVEhQYjlUT0RPa0tiSTVaellJc21jSCs4RW5nQmxIaGs0WFd3eFhaWVZUQVpWeHZ0TFF4dHJhUGhnOUx4QStPbVpnbnVLcjN0UDNLSFN1TVRnWUxhKzEyQzRWV1laR0dvTW1uclNpNTJVcTR4V29XSlloYW9jTnVOM29SMGc5SnlKc3dnZEJnbGF3dU1BaGhsbWYybVNKV2pzZkRxM214bXVhZzIwZFlDR0VtWk1lVHVXWkttZGRiZHZiTXBLY0YzMklOeUpcL1hvVUhkekR1bzdIbjlCQ1VHcHVaSm10aVVURmZGTjdzU0p2emR6Y25uMHA5Y3FBVkFuNzFcLytwcGhQejBQdmZQMzJiVjYwRjFxWUdyQmV3R3FkbE54TUZzeGZOVHJsdjc4K1wvemk5T1ZnYkltV0hXUHJcL2ZjeCtlbWl1dTZDU2xHbG0xY0NPaUhhMzdONkpmUDVsOHY0V3VuNlRKNmxBK3FPa3hlaFJvaUNtdUdXdFJMOXZDMk5mR3NIaVJyMng0WjVOTjZtd0tPR1NoTWZ6M0c1aGZxQm9YWWZYeHhkSDdcLzRSeVFwVWRwaklrR3FmS0VEMUxHbWozajg3blJuOWVYV1loK2pcLzBIZG0rVnVGRkFNQUFBPT0iLCJzdWIiOiJhZG1pbiIsInJvbGVzIjpbIlJPTEVfTk9fUk9MRVMiXSwiZXhwIjoxNDk0OTI5MDE1LCJpYXQiOjE0OTQ5MjU0MTV9.R_UIO2sQ6Q6gPBPIcypQJRawHJroLPyxbKbUSNQfQLE, expiration:2443, refreshToken:null, principal:grails.plugin.springsecurity.userdetails.GrailsUser@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_NO_ROLES, super:grails.plugin.springsecurity.rest.token.AccessToken@8d3530c3: Principal: grails.plugin.springsecurity.userdetails.GrailsUser@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_NO_ROLES; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_NO_ROLES)
DEBUG grails.plugin.springsecurity.rest.RestTokenValidationFilter - Continuing the filter chain
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles at position 6 of 7 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles at position 7 of 7 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
TRACE grails.plugin.springsecurity.web.access.intercept.InterceptUrlMapFilterInvocationDefinition - getAttributes(): url is /pcsbackend/settings/getallpromptfiles for FilterInvocation FilterInvocation: URL: /pcsbackend/settings/getAllPromptFiles
TRACE grails.plugin.springsecurity.web.access.intercept.InterceptUrlMapFilterInvocationDefinition - new candidate for '/pcsbackend/settings/getallpromptfiles': '/**':[ROLE_NO_ROLES]
TRACE grails.plugin.springsecurity.web.access.intercept.InterceptUrlMapFilterInvocationDefinition - config for '/pcsbackend/settings/getallpromptfiles' is '/**':[ROLE_NO_ROLES]
TRACE grails.plugin.springsecurity.web.access.intercept.InterceptUrlMapFilterInvocationDefinition - ConfigAttributes are [ROLE_NO_ROLES]
DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /pcsbackend/settings/getAllPromptFiles; Attributes: [ROLE_NO_ROLES]
DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: grails.plugin.springsecurity.rest.token.AccessToken(accessToken:eyJhbGciOiJIUzI1NiJ9.eyJwcmluY2lwYWwiOiJINHNJQUFBQUFBQUFBSlZTUDBcL2JRQlJcL0RvbEFRbENvVkNRR3VoUzJ5cEhhTVZOQmdJU3NwR3FhQlNUUXhYNjRCK2M3OSs0TXlZSXl3Y0FBb2tXcTJxXC9BTjRHRkQxQ1ZnWldabFhlRzRNQ0Nlb3V0ZHpcL1wvXC9qMmYzVURGYVBnWWE4YUY4Vk9SeFZ6Nkp0VmN4Z2JEVEhQYjlUT0RPa0tiSTVaellJc21jSCs4RW5nQmxIaGs0WFd3eFhaWVZUQVpWeHZ0TFF4dHJhUGhnOUx4QStPbVpnbnVLcjN0UDNLSFN1TVRnWUxhKzEyQzRWV1laR0dvTW1uclNpNTJVcTR4V29XSlloYW9jTnVOM29SMGc5SnlKc3dnZEJnbGF3dU1BaGhsbWYybVNKV2pzZkRxM214bXVhZzIwZFlDR0VtWk1lVHVXWkttZGRiZHZiTXBLY0YzMklOeUpcL1hvVUhkekR1bzdIbjlCQ1VHcHVaSm10aVVURmZGTjdzU0p2emR6Y25uMHA5Y3FBVkFuNzFcLytwcGhQejBQdmZQMzJiVjYwRjFxWUdyQmV3R3FkbE54TUZzeGZOVHJsdjc4K1wvemk5T1ZnYkltV0hXUHJcL2ZjeCtlbWl1dTZDU2xHbG0xY0NPaUhhMzdONkpmUDVsOHY0V3VuNlRKNmxBK3FPa3hlaFJvaUNtdUdXdFJMOXZDMk5mR3NIaVJyMng0WjVOTjZtd0tPR1NoTWZ6M0c1aGZxQm9YWWZYeHhkSDdcLzRSeVFwVWRwaklrR3FmS0VEMUxHbWozajg3blJuOWVYV1loK2pcLzBIZG0rVnVGRkFNQUFBPT0iLCJzdWIiOiJhZG1pbiIsInJvbGVzIjpbIlJPTEVfTk9fUk9MRVMiXSwiZXhwIjoxNDk0OTI5MDE1LCJpYXQiOjE0OTQ5MjU0MTV9.R_UIO2sQ6Q6gPBPIcypQJRawHJroLPyxbKbUSNQfQLE, expiration:2443, refreshToken:null, principal:grails.plugin.springsecurity.userdetails.GrailsUser@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_NO_ROLES, super:grails.plugin.springsecurity.rest.token.AccessToken@8d3530c3: Principal: grails.plugin.springsecurity.userdetails.GrailsUser@586034f: Username: admin; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_NO_ROLES; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_NO_ROLES)
DEBUG org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl - getReachableGrantedAuthorities() - From the roles [ROLE_NO_ROLES] one can reach [ROLE_NO_ROLES] in zero or more steps.
TRACE grails.plugin.springsecurity.access.vote.AuthenticatedVetoableDecisionManager - decide(): authenticatedVotersGranted=false otherVotersGranted=true
DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Authorization successful
DEBUG org.springframework.security.web.access.intercept.FilterSecurityInterceptor - RunAsManager did not change Authentication object
DEBUG org.springframework.security.web.FilterChainProxy - /pcsbackend/settings/getAllPromptFiles reached end of additional filter chain; proceeding with original chain
DEBUG org.springframework.security.web.access.ExceptionTranslationFilter - Chain processed normally
Requested URI is: /umm/pcsbackend/settings/getAllPromptFiles
Name of the microservice is: pcsbackend
Name of the controller is: settings
Name of the action is: getAllPromptFiles
If authorized, request will be forwarded to: http://192.168.1.79:8080/pcsbackend/settings/getAllPromptFiles
Logged in user is null

and the obvious response:

{
"status": {
"enumType": "org.springframework.http.HttpStatus",
"name": "FORBIDDEN"
},
"message": "Access denied. Token not provided in the header."
}

The whole project is available here if anyone wants to reproduce the issue on his machine. You can also open a pull request if the code is buggy. 📦

~## How to reproduce~

Look here: https://github.com/grails-plugins/grails-spring-security-core/issues/490#issuecomment-355517329 for reproducing the issue.

Update: May 19, 2017

I tried deploying my war in a Tomcat on my local machine. It still behaves the same. I also tried disabling tomcat cache and 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.
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.


Regards

saqib-ahmed commented 7 years ago

I got a workaround fix. springSecurityService is still returning null. I manually decoded the API token from the header and extracted username from it. This resolves my problem for now because I only needed the username. It is still incomprehensible that why the plugin is behaving this way. I'm not closing the issue yet.

    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-"\""
    }
sdelamo commented 7 years ago

I will check the issue @saqibahmed515 but I did not have the time yet.

pangeaos commented 6 years ago

I'm having same issue. Only when I create the war for tomcat 8.5 def user = springSecurityService.currentUser if(!user){ log.error "user not found." }

sdelamo commented 6 years ago

@barcelona23 do you have a sample project ?

saqib-ahmed commented 6 years ago

@sdelamo Kindly have a look at following project: https://github.com/saqibahmed515/demoSpringSecurityIssue

Steps to reproduce:

  1. Configure DB setting in application.yml. I'm using mysql with DB name demo.
  2. Build the application using grails war or ./gradlew assemble
  3. Insert *.war file in the ..../tomcat/webapps/.
  4. Access localhost:8080/{appName}/user/index. Credentials are admin:admin.
  5. You'd see from GSP view that springSecurityService has perfect value in the interceptor but springSecurityService.currentUser is null. Getting current user here: https://github.com/saqibahmed515/demoSpringSecurityIssue/blob/master/grails-app/controllers/com/demo/issue/UserInterceptor.groovy#L16

Using

Grails

saqib-ahmed commented 6 years ago

I'm getting following response when the application is deployed in above mentioned environment: image

bilgehanm commented 3 years ago

I have a similar problem. In my scenario i create a user that authenticates via external oauth 2 server and automatically login using springsecurity.reauthenticate. On jetbrains Idea that works but when deployed on tomcat, user has to logout first and login again to load user roles. When i list roles using ${currentUser?.authorities} it shows all the roles but on tomcat debug log, it says Authorities: ROLE_NO_ROLES. User first have to logout and login again.