2
votes

I have configured a Grails(2.3.7) app using spring-security-core:2.0.0 + spring-security-rest:1.4.1 plugins in order to have two auth types, a statefull auth for web and one for mobile using tokens(stateless). All good, basic http auth is working well. Trying to get authenticated using POSTMAN rest client to http://localhost:8080/api/login having username and password in the request payload i get 401 Unauthorized , I'm not able to understand why?What is missing from below configuration? Any help is highly appreciated. I tried as well with spring-security-rest:1.5.0 but i got the same result, 401.

BuildConfig.groovy

 plugins {
   ...
    compile ":spring-security-core:2.0.0"
    compile ":spring-security-rest:1.4.1", {
        excludes ('spring-security-core')
    }
...
}

Config.groovy

   / Added by the Spring Security Core plugin:
grails.plugin.springsecurity.successHandler.defaultTargetUrl = '/general'
grails.plugin.springsecurity.userLookup.userDomainClassName = 'org.sali.Users.SecUser'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'org.sali.Users.SecUserSecRole'
grails.plugin.springsecurity.authority.className = 'org.sali.Users.SecRole'
grails.plugin.springsecurity.securityConfigType = "Annotation"

grails.plugin.springsecurity.roleHierarchy = '''
    ROLE_ADMIN > ROLE_OPERATOR
'''
grails.plugin.springsecurity.useSwitchUserFilter = true

grails.plugin.springsecurity.controllerAnnotations.staticRules = [
        '/j_spring_security_switch_user': ['permitAll'],
        '/api/**': ['permitAll']
]


grails.plugin.springsecurity.filterChain.chainMap = [
        //'/api/**': 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter',// Stateless chain
        '/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter',
        '/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter',                                          // Traditional chain
]
//gorm
grails.plugin.springsecurity.rest.token.storage.useGorm = true
grails.plugin.springsecurity.rest.token.storage.gorm.tokenDomainClassName = 'org.sali.Rest.AuthenticationToken'
grails.plugin.springsecurity.rest.token.storage.gorm.tokenValuePropertyName = 'token'
grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyName = 'username'


//login
grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.useJsonCredentials = true
grails.plugin.springsecurity.rest.login.failureStatusCode = 401
grails.plugin.springsecurity.rest.login.usernamePropertyName = 'username'
grails.plugin.springsecurity.rest.login.passwordPropertyName='password'
grails.plugin.springsecurity.rest.login.endpointUrl='/api/login'
grails.plugin.springsecurity.rest.login.useRequestParamsCredentials = false

//logout
grails.plugin.springsecurity.rest.logout.endpointUrl='/api/logout'

//token generation
grails.plugin.springsecurity.rest.token.generation.useUUID=false
grails.plugin.springsecurity.rest.token.generation.useSecureRandom=true

//token rendering
grails.plugin.springsecurity.rest.token.rendering.usernamePropertyName='username'
grails.plugin.springsecurity.rest.token.rendering.authoritiesPropertyName='roles'
grails.plugin.springsecurity.rest.token.rendering.tokenPropertyName='token'

//token validate
grails.plugin.springsecurity.rest.token.validation.useBearerToken = true

//if disable 'Bearer', you can configure a custom header.
//grails.plugin.springsecurity.rest.token.validation.useBearerToken = false
//grails.plugin.springsecurity.rest.token.rendering.tokenPropertyName   access_token
//grails.plugin.springsecurity.rest.token.validation.headerName = 'x-auth-token'
grails.plugin.springsecurity.rest.token.validation.active=true
grails.plugin.springsecurity.rest.token.validation.endpointUrl='/api/validate'



//grails.plugin.springsecurity.rest.token.validation.headerName = 'X-Auth-Token'
//grails.plugin.springsecurity.rest.token.validation.useBearerToken = false

//grails.plugin.springsecurity.password.algorithm = 'SHA-256'
//grails.plugin.springsecurity.password.hash.iterations = 1

//cors

cors.enabled=true
cors.url.pattern = '/api/*'
cors.headers=[
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': true,
        'Access-Control-Allow-Headers': 'origin, authorization, accept, content-type, x-requested-with,X-Auth-Token',
        'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS',
        'Access-Control-Max-Age': 3600
]

UrlMappings.groovy

class UrlMappings {

    static mappings = {
        "/$controller/$action?/$id?"{
            constraints {
                // apply constraints here
            }
        }

        "/"(controller: "login")
        "404"(view:'/error')
        "405"(view:'/error')
        "500"(view:'/error')
        "/login/$action?"(controller: "login")
        "/logout/$action?"(controller: "logout")

    }
}

Any ideas are very welcomed. Thx

2
I think first you should put a breakpoint in your controller to check if the request actually reached there or not.Ankit Agrawal
What controller do you mean?As I know spring security rest plugin expose himself this /api/login for auth. Even if i put a breakpoint, as you said, it will not be reached.user226578
Your configuration seems to be correct. If I am not wrong, in case the login fails, server is going to respond with a 401 error code due to this configuration - grails.plugin.springsecurity.rest.login.failureStatusCode = 401 . Break point's idea was to confirm that request reached to the backend code and there is nothing wrong with the filters for that particular url.Ankit Agrawal
It would also be useful if you enable logs for grails.plugin.springsecurity and org.springframework. This link would help you to enable logs.Ankit Agrawal
that's a good idea. i'm just wondering...the 401 could be caused by the filters from chainMap, should i add something in UrlMappings in order to expose and enable the /api/login? I'm sure I'm missing something in configuration.user226578

2 Answers

0
votes

After adding these in Config.groovy in worked:

grails.plugin.springsecurity.password.algorithm = 'SHA-256'
grails.plugin.springsecurity.password.hash.iterations = 1
0
votes

If someone else still looking for a solution to this, and tried the rules with no luck, check if the classes are correct:

grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.site.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.site.UserRole'
grails.plugin.springsecurity.authority.className = 'com.site.Role'

In my case, I had the class com.site.User and I had set up com.site.user.User, which generated this problem!

Ref: https://github.com/alvarosanchez/grails-spring-security-rest/issues/181#issuecomment-82260495