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