Search code examples
grailsspring-securitygrails-spring-security

Grails Spring Security Rest 400 BAD REQUEST ERROR


I have been trying to authenticate the grails spring security rest url /api/login using curl in windows. But unable to do so. I've always ended up with 400 BAD REQUEST ERROR. These are my configuration

BuildConfig.groovy

compile ":asset-pipeline:2.5.7"
compile ":spring-security-core:2.0.0"
compile ":spring-security-rest:1.5.4", {
    excludes: 'spring-security-core'
}
// plugins needed at runtime but not for compilation
runtime ":hibernate4:4.3.10" // or ":hibernate:3.6.10.18"
runtime ":database-migration:1.4.0"
runtime ":jquery:1.11.1"
runtime "org.grails.plugins:mysql-connectorj:5.1.22.1"
runtime ":cors:1.1.6"

====================================================================

Config.groovy

// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.aes.apprater.SecUser'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.aes.apprater.SecUserSecRole'
grails.plugin.springsecurity.authority.className = 'com.aes.apprater.SecRole'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    '/':                ['permitAll'],
    '/index':           ['permitAll'],
    '/index.gsp':       ['permitAll'],
    '/assets/**':       ['permitAll'],
    '/**/js/**':        ['permitAll'],
    '/**/css/**':       ['permitAll'],
    '/**/images/**':    ['permitAll'],
    '/**/favicon.ico':  ['permitAll']
]

grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugin.springsecurity.interceptUrlMap = [
    '/project/**':         ['ROLE_ADMIN'],
    '/appRater/**':        ['ROLE_ADMIN'],
    '/mobilePlatform/**':  ['ROLE_ADMIN'],
    '/**':               ['IS_AUTHENTICATED_ANONYMOUSLY']
]

grails.plugin.springsecurity.filterChain.chainMap = [
    '/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter',  // Stateless chain
    '/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'                                                                          // Traditional chain
]

grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.failureStatusCode=401
grails.plugin.springsecurity.rest.token.validation.active=true

Output:

C:\Users\admin>curl -i -X POST -H "Content-Type: application/json" -d '{"usernam
e":"xxxxx", "password":"xxxx"}' http://localhost:8080/xxxx-2.0/api/login
curl: (3) [globbing] unmatched close brace/bracket in column 14
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Fri, 28 Apr 2017 09:16:44 GMT
Connection: close

DEBUG LOGS:

|Loading Grails 2.5.6
|Configuring classpath
.
|Environment set to development
.................................
|Packaging Grails application
.............................................
|Running Grails application
Configuring Spring Security Core ...
... finished configuring Spring Security Core
Configuring Spring Security REST ...
... finished configuring Spring Security REST
2017-05-02 13:10:00,852 [localhost-startStop-1] DEBUG intercept.FilterSecurityInterceptor  - Validated configuration attributes
2017-05-02 13:10:04,407 [localhost-startStop-1] DEBUG hierarchicalroles.RoleHierarchyImpl  - setHierarchy() - The following role hierarchy was set: 
2017-05-02 13:10:04,425 [localhost-startStop-1] INFO  web.DefaultSecurityFilterChain  - Creating filter chain: Ant [pattern='/api/**'], [grails.plugin.springsecurity.web.SecurityRequestHolderFilter@243ac73f, grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter@eef0bae, grails.plugin.springsecurity.rest.RestAuthenticationFilter@6fe7d42a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d1a4acb, grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter@6924852d, grails.plugin.springsecurity.rest.RestTokenValidationFilter@5ca38348, org.springframework.security.web.access.ExceptionTranslationFilter@73001b7b, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@c0c6339]
2017-05-02 13:10:04,425 [localhost-startStop-1] INFO  web.DefaultSecurityFilterChain  - Creating filter chain: Ant [pattern='/**'], [grails.plugin.springsecurity.web.SecurityRequestHolderFilter@243ac73f, org.springframework.security.web.context.SecurityContextPersistenceFilter@146395d, grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter@eef0bae, grails.plugin.springsecurity.web.authentication.GrailsUsernamePasswordAuthenticationFilter@29600952, grails.plugin.springsecurity.rest.RestAuthenticationFilter@6fe7d42a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d1a4acb, grails.plugin.springsecurity.web.filter.GrailsRememberMeAuthenticationFilter@6003fbb6, grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter@6924852d, org.springframework.security.web.access.ExceptionTranslationFilter@25829af9, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@c0c6339]
|Server running. Browse to http://localhost:8090/apprater-2.0
.2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy  - /index.gsp at position 3 of 10 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy  - /index.gsp at position 4 of 10 in additional filter chain; firing Filter: 'GrailsUsernamePasswordAuthenticationFilter'
2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy  - /index.gsp at position 5 of 10 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
.2017-05-02 13:10:06,285 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy  - /index.gsp at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-05-02 13:10:06,287 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy  - /index.gsp at position 7 of 10 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2017-05-02 13:10:06,288 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy  - /index.gsp at position 8 of 10 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
.2017-05-02 13:10:06,300 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy  - /index.gsp reached end of additional filter chain; proceeding with original chain
.2017-05-02 13:10:07,785 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository  - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper  - Skip invoking on
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper  - Skip invoking on
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper  - Skip invoking on
2017-05-02 13:10:07,788 [http-bio-8090-exec-10] DEBUG access.ExceptionTranslationFilter  - Chain processed normally
2017-05-02 13:10:07,788 [http-bio-8090-exec-10] DEBUG context.SecurityContextPersistenceFilter  - SecurityContextHolder now cleared, as request processing completed
2017-05-02 13:10:14,009 [http-bio-8090-exec-2] DEBUG matcher.AntPathRequestMatcher  - Checking match of request : '/api/login'; against '/api/**'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy  - /api/login at position 1 of 8 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy  - /api/login at position 2 of 8 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy  - /api/login at position 3 of 8 in additional filter chain; firing Filter: 'RestAuthenticationFilter'

Solution

  • Finally after writing a test case in grails controller, it was the curl throwing 400 bad request error. There's nothing wrong with the configuration. The below test case proved it.

    when: 'login with the admin'        
            RestBuilder rest = new RestBuilder()        
            def resp = rest.post("http://localhost:${serverPort}/xxx/api/login") { 
                accept('application/json')
                contentType('application/json')
                json {
                    username = 'xxx'
                    password = 'xxx'
                }
            }
    
            then:        
            resp.status == 200
            resp.json.roles.find { it == 'ROLE_ADMIN' }
    
            when:
            def accessToken = resp.json.access_token
    
            then:
            accessToken        
    
            when:
            resp = rest.get("http://localhost:${serverPort}/xxx/appRaterRest/index") {
                accept('application/json')
                header('Authorization', "Bearer ${accessToken}" ) 
            }
    
            then:        
            resp.status == 200