Search code examples
springgrailsgroovyspring-security-rest

A component required a bean named '' that could not be found


I'm trying to build my first grails application using grails-spring-security-rest plugin following this post's instructions.

However, when I try to run the application it gives me the following output:

| Running application...
2017-05-07 20:18:54.614  WARN --- [           main] g.p.s.SpringSecurityCoreGrailsPlugin     : 
Configuring Spring Security Core ...

Configuring Spring Security Core ...
2017-05-07 20:18:54.688  WARN --- [           main] g.p.s.SpringSecurityCoreGrailsPlugin     : ... finished configuring Spring Security Core

... finished configuring Spring Security Core


Configuring Spring Security REST 2.0.0.M2...
... finished configuring Spring Security REST

        ... with GORM support
2017-05-07 20:19:00.278 DEBUG --- [ost-startStop-1] o.s.s.w.a.i.FilterSecurityInterceptor    : Validated configuration attributes
2017-05-07 20:19:00.527 DEBUG --- [ost-startStop-1] g.p.s.r.t.g.jwt.FileRSAKeyProvider       : Loading public/private key from DER files
2017-05-07 20:19:00.531 DEBUG --- [ost-startStop-1] g.p.s.r.t.g.jwt.FileRSAKeyProvider       : Public key path: /mnt/dev/Workspaces/LZR.RAS/RAS-API/security/public_key.der
2017-05-07 20:19:00.538 DEBUG --- [ost-startStop-1] g.p.s.r.t.g.jwt.FileRSAKeyProvider       : Private key path: /mnt/dev/Workspaces/LZR.RAS/RAS-API/security/private_key.der
2017-05-07 20:19:00.612 DEBUG --- [ost-startStop-1] g.p.s.rest.RestTokenValidationFilter     : Initializing filter 'restTokenValidationFilter'
2017-05-07 20:19:00.612 DEBUG --- [ost-startStop-1] g.p.s.rest.RestTokenValidationFilter     : Filter 'restTokenValidationFilter' configured successfully
2017-05-07 20:19:00.612 DEBUG --- [ost-startStop-1] o.s.s.w.a.ExceptionTranslationFilter     : Initializing filter 'restExceptionTranslationFilter'
2017-05-07 20:19:00.612 DEBUG --- [ost-startStop-1] o.s.s.w.a.ExceptionTranslationFilter     : Filter 'restExceptionTranslationFilter' configured successfully
2017-05-07 20:19:00.613 DEBUG --- [ost-startStop-1] o.s.security.web.FilterChainProxy        : Initializing filter 'filterChainProxy'
2017-05-07 20:19:00.613 DEBUG --- [ost-startStop-1] o.s.security.web.FilterChainProxy        : Filter 'filterChainProxy' configured successfully
2017-05-07 20:19:00.613 DEBUG --- [ost-startStop-1] g.p.s.rest.RestLogoutFilter              : Initializing filter 'restLogoutFilter'
2017-05-07 20:19:00.613 DEBUG --- [ost-startStop-1] g.p.s.rest.RestLogoutFilter              : Filter 'restLogoutFilter' configured successfully
2017-05-07 20:19:00.613 DEBUG --- [ost-startStop-1] g.p.s.rest.RestAuthenticationFilter      : Initializing filter 'restAuthenticationFilter'
2017-05-07 20:19:00.613 DEBUG --- [ost-startStop-1] g.p.s.rest.RestAuthenticationFilter      : Filter 'restAuthenticationFilter' configured successfully
2017-05-07 20:19:02.731 DEBUG --- [           main] o.s.s.a.h.RoleHierarchyImpl              : setHierarchy() - The following role hierarchy was set: 
2017-05-07 20:19:03.064 ERROR --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

A component required a bean named '' that could not be found.


Action:

Consider defining a bean named '' in your configuration.

Here is my application.yml content:

---
grails:
    profile: rest-api
    codegen:
        defaultPackage: ras
    spring:
        transactionManagement:
            proxies: false
info:
    app:
        name: '@info.app.name@'
        version: '@info.app.version@'
        grailsVersion: '@info.app.grailsVersion@'
spring:
    main:
        banner-mode: "off"
    groovy:
        template:
            check-template-location: false

# Spring Actuator Endpoints are Disabled by Default
endpoints:
    enabled: false
    jmx:
        enabled: true

---
grails:
    mime:
        disable:
            accept:
                header:
                    userAgents:
                        - Gecko
                        - WebKit
                        - Presto
                        - Trident
        types:
            json:
              - application/json
              - text/json
            hal:
              - application/hal+json
              - application/hal+xml
            xml:
              - text/xml
              - application/xml
            atom: application/atom+xml
            css: text/css
            csv: text/csv
            js: text/javascript
            rss: application/rss+xml
            text: text/plain
            all: '*/*'
    urlmapping:
        cache:
            maxsize: 1000
    controllers:
        defaultScope: singleton
    converters:
        encoding: UTF-8

---
hibernate:
    cache:
        queries: false
        use_second_level_cache: true
        use_query_cache: false
        region.factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory

dataSource:
    pooled: true
    jmxExport: true
    driverClassName: com.mysql.jdbc.Driver
    dialect: org.hibernate.dialect.MySQL5InnoDBDialect
    username: *******
    password: *******

environments:
    development:
        dataSource:
            dbCreate: create-drop
            url: jdbc:mysql://localhost:3306/ras_dev?autoReconnect=true&useUnicode=yes&characterEncoding=UTF-8&useSSL=false
    test:
        dataSource:
            dbCreate: create-drop
            url: jdbc:mysql://localhost:3306/ras_test?autoReconnect=true&useUnicode=yes&characterEncoding=UTF-8&useSSL=false
    production:
        dataSource:
            dbCreate: update
            url: jdbc:mysql://localhost:3306/ras?autoReconnect=true&useUnicode=yes&characterEncoding=UTF-8
            properties:
                jmxEnabled: true
                initialSize: 5
                maxActive: 50
                minIdle: 5
                maxIdle: 25
                maxWait: 10000
                maxAge: 600000
                timeBetweenEvictionRunsMillis: 5000
                minEvictableIdleTimeMillis: 60000
                validationQuery: SELECT 1
                validationQueryTimeout: 3
                validationInterval: 15000
                testOnBorrow: true
                testWhileIdle: true
                testOnReturn: false
                jdbcInterceptors: ConnectionState
                defaultTransactionIsolation: 2 # TRANSACTION_READ_COMMITTED

application.groovy

grails.plugin.springsecurity.useSecurityEventListener = true
grails.plugin.springsecurity.securityConfigType = 'InterceptUrlMap'

grails.plugin.springsecurity.rememberMe.persistent = true

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

grails.plugin.springsecurity.rest.token.storage.jwt.useEncryptedJwt = true
grails.plugin.springsecurity.rest.token.storage.jwt.privateKeyPath = 'security/private_key.der'
grails.plugin.springsecurity.rest.token.storage.jwt.publicKeyPath = 'security/public_key.der'

grails.plugin.springsecurity.rest.token.rendering.authoritiesPropertyName = 'permissions'
grails.plugin.springsecurity.rest.token.rendering.usernamePropertyName = 'username'

grails.plugin.springsecurity.rest.token.generation.useSecureRandom = true

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

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

grails.plugin.springsecurity.interceptUrlMap = [
    [pattern: '/',               access: ['permitAll']],
    [pattern: '/assets/**',      access: ['permitAll']],
    [pattern: '/partials/**',    access: ['permitAll']],
    [pattern: '/**/js/**',       access: ['permitAll']],
    [pattern: '/**/css/**',      access: ['permitAll']],
    [pattern: '/**/images/**',   access: ['permitAll']],
    [pattern: '/**/favicon.ico', access: ['permitAll']],
    [pattern: '/api/login',      access: ['permitAll']],
    [pattern: '/api/logout',     access: ['isFullyAuthenticated()']],
    [pattern: '/api/validate',   access: ['isFullyAuthenticated()']],
    [pattern: '/**',             access: ['isFullyAuthenticated()']]
]

resources.groovy

import ras.bean.DefaultSecurityEventListener
import ras.auth.DefaultJsonPayloadCredentialsExtractor

beans = {
    credentialsExtractor(DefaultJsonPayloadCredentialsExtractor)
    defaultSecurityEventListener(DefaultSecurityEventListener)
}

grails version:

$ grails --version
| Grails Version: 3.2.6
| Groovy Version: 2.4.7
| JVM Version: 1.8.0_121

UPDATE 1

I have added following lines to logback.groovy

logger("org.springframework.security", DEBUG, ['STDOUT'], false)
logger("grails.plugin.springsecurity", DEBUG, ['STDOUT'], false)
logger("org.pac4j", DEBUG, ['STDOUT'], false)

Yet, the console output and stacktrace.log file have the same output as posted above

I would really appreciate any suggestions on how to fix this error.


Solution

  • Finally, I was able to fix the problem:

    Issue 1: I created User Role and UserRole classes manually instead of using

    grails s2-quickstart com.app-name User Role
    

    as described here

    Issue 2: I used the wrong format for chainMap filters. Here is the one that worked for me

    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: '/api/**',    filters: 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter'], // Stateless chain
        [pattern: '/data/**',   filters: 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter'], // Stateless chain
        [pattern: '/**',        filters: 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter']   // Traditional chain
    ]