Grails Security Annotations, #Secured(['ROLE_ADMIN']) not displaying content for role - grails

I'm trying to render some content for all users and some for the ROLE_ADMIN. I can login as both the adminuser and useruser (authed via CAS) but see the same content for both
Here's the controller
package college.infotech.edu
import java.awt.GraphicsConfiguration.DefaultBufferCapabilities;
import grails.plugin.springsecurity.annotation.Secured
class SecureController {
#Secured(['ROLE_ADMIN', 'ROLE_USER'])
def index() {
render 'All Users see this'
def showUserName
render "<br />"
render request.remoteUser
#Secured(['ROLE_ADMIN'])
def showAdmin = {
render "<br />"
render "admin users see this"
}
}
Here's my bootstrap.groovy (which has been working and does authenticate via CAS
.......
def init = { servletContext ->
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = new Role(authority: 'ROLE_USER').save(flush: true)
def testUser = new AppUser(username: 'adminuser', password:'password', enabled: true, accountExpired: false, accountLocked: false, passwordExpired: false)
testUser.save(flush: true)
def testUser2 = new AppUser(username: 'useruser', password:'password', enabled: true, accountExpired: false, accountLocked: false, passwordExpired: false)
testUser2.save(flush: true)
UserRole.create testUser, adminRole, true
UserRole.create testUser2, userRole, true
assert AppUser.count() == 2
assert Role.count() == 2
assert UserRole.count() == 2
}
.......
Here's some relevant logs entries
[http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /secure/index; Attributes: [ROLE_ADMIN, ROLE_USER]
[http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.cas.authentication.CasAuthenticationToken#5d4cb3a4: Principal: grails.plugin.springsecurity.userdetails.GrailsUser#17617e0a: Username: adminuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: CCFEACE94A4EC5FFB3B13ACA0E06BB1A; Granted Authorities: ROLE_ADMIN Assertion: org.jasig.cas.client.validation.AssertionImpl#37b7e6ad [http-bio-8080-exec-8] DEBUG hierarchicalroles.RoleHierarchyImpl - getReachableGrantedAuthorities() - From the roles [ROLE_ADMIN] one can reach [ROLE_ADMIN] in zero or more steps.
[http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Authorization successful

That's a weird looking controller action. It's a method called index secured with either ROLE_ADMIN or ROLE_USER, and multiple render calls and a mysterious annotated showAdmin closure. In general you should only have one render call, and if Grails concatenates the rendered output from multiple calls for you, you should consider it a bug that will be fixed at some point.
The inner showAdmin closure isn't doing anything. It's just a closure in the middle of a method, and it's not called by Grails or your code. Since it's just an object inside a method, it's not seen by Grails as a callable action, and it's not seen by Spring Security as something to be guarded or processed.

Related

Grails Security 3.1.2 login of user with role ROLE_ADMIN shows ROLE_NO_ROLES as authorities

I'm testing Grails 3.2.9 with Sec plugin 3.1.2.
Created a user with role ROLE_ADMIN in bootstrap, and added permissions on interceptUrlMap for a test controller "note". After a successful login with that user, I see on the logs my admin has ROLE_NO_ROLES and is denied access to note controller.
User, role and user role association is on the database.
def adminRole = Role.findOrSaveByAuthority('ROLE_ADMIN')
def admin = new User(username: 'admin', password: 'admin').save()
UserRole.create admin, adminRole
application.groovy
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.cabolabs.security.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.cabolabs.security.UserRole'
grails.plugin.springsecurity.authority.className = 'com.cabolabs.security.Role'
grails.plugin.springsecurity.authority.groupAuthorityNameField = 'authorities'
grails.plugin.springsecurity.useRoleGroups = true
...
grails.plugin.springsecurity.interceptUrlMap = [
[pattern: '/note/**', access: ['ROLE_ADMIN']],
[pattern: '/patient/**', access: ['ROLE_ADMIN']],
[pattern: '/login/**', access: ['permitAll']],
[pattern: '/logout', access: ['permitAll']],
[pattern: '/logout/**', access: ['permitAll']],
[pattern: '/dbconsole/**', access: ['permitAll']],
[pattern: '/**', access: ["IS_AUTHENTICATED_FULLY"]]
]
...
Logs after login, when I try to go to /note/index
2017-05-11 23:32:15.793 DEBUG --- [nio-8091-exec-4] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#8d34560b: 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: org.springframework.security.web.authentication.WebAuthenticationDetails#166c8: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: F0902A19E19C23D30B452C332C6C5728; Granted Authorities: ROLE_NO_ROLES
2017-05-11 23:32:15.793 DEBUG --- [nio-8091-exec-4] o.s.s.a.h.RoleHierarchyImpl : getReachableGrantedAuthorities() - From the roles [ROLE_NO_ROLES] one can reach [ROLE_NO_ROLES] in zero or more steps.
2017-05-11 23:32:15.805 DEBUG --- [nio-8091-exec-4] tContextHolderExceptionTranslationFilter : Access is denied (user is not anonymous); delegating to AccessDeniedHandler
Any ideas of what is going on?
Tried to find pointer on the Sec plugin documentation, but it just mentions ROLE_NO_ROLES once and that is assigned when the user has no roles, that is not this case.
If you have useRoleGroups = true you have to populate your database with :
Role adminRole = new Role("ROLE_ADMIN").save()
RoleGroup adminGroup = new RoleGroup("GROUP_ADMIN").save()
RoleGroupRole.create(adminGroup, adminRole, true)
User user = new User("<username>", "<password>").save()
UserRoleGroup.create(user, adminGroup, true)
instead of
def adminRole = Role.findOrSaveByAuthority('ROLE_ADMIN')
def admin = new User(username: 'admin', password: 'admin').save()
UserRole.create admin, adminRole

Hapi Bell Twitter Auth with email

I'm struggling to get the email address of twitter users when they login
I get the following error from Joi "Error: Uncaught error: Invalid options value: must be true, falsy or an object"
server.auth.strategy('twitter', 'bell', {
provider: 'twitter',
scope: ['public_profile', 'email'],
config: {
extendedProfile: true,
getParams: 'include_email',
getMethod: 'account/verify'
},
password: config.longpass, //Use something more secure in production
clientId: config.twitter_key,
clientSecret: config.twitter_secret,
isSecure: config.useHttps //Should be set to true (which is the default) in production
});
This code works for me.
server.auth.strategy('twitter', 'bell', {
provider: 'twitter',
config: {
getMethod: 'account/verify_credentials',
getParams: {include_email:'true' },//doesn't work without quotes!
},
password: 'secret_cookie_encryption_password', //Use something more secure in production
clientId: secret.twitterId,
clientSecret: secret.twitterSecret,
isSecure: false //Should be set to true (which is the default) in production
});
Don't forget to allow necessary permission (Request email addresses from users) in your Twitter application settings.

Grails Spring Security LDAP "defaultRole" does not get assigned

I'm struggling with LDAP authorization in Grails (authentication works). This is my configuration:
grails.plugin.springsecurity.ldap.auth.hideUserNotFoundExceptions = false
grails.plugin.springsecurity.ldap.search.filter = 'sAMAccountName={0}'
grails.plugin.springsecurity.ldap.search.searchSubtree = true
grails.plugin.springsecurity.ldap.authorities.ignorePartialResultException = true
grails.plugin.springsecurity.ldap.authorities.defaultRole = 'ROLE_USER'
grails.plugin.springsecurity.ldap.authorities.retrieveDatabaseRoles = true
grails.plugin.springsecurity.ldap.authorities.retrieveGroupRoles = false
grails.plugin.springsecurity.ldap.useRememberMe = false
I'm expection the user to get assigned the 'ROLE_USER' role but all I get is:
DEBUG org.springframework.security.web.context.HttpSessionSecurityContextRepository - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl#d66fe506: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#d66fe506: Principal: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl#d66d0e48: Dn: cn=testuser,cn=Users,dc=GROUP,dc=LOCAL; Username: testuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: 2BA8D2C334CBDA358EEEAD97F12DD38C; Not granted any authorities'
Do you have any word of wisdom? What am I doing wrong?
Just for the record I found out the solution is to switch retrieveGroupRoles to true:
grails.plugin.springsecurity.ldap.authorities.retrieveGroupRoles = true

grails with spring security can't with create default user in BootStrap

I'm using Grails with Spring Security plugin and want to create default User when application starts.
I have default User and Authority classes
My BootStrap.groovy is as follows:
class BootStrap {
def init = { servletContext ->
def userAuthority = Authority.findByAuthority('ROLE_USER') ?: new Authority(authority: 'ROLE_USER').save(flush: true)
def adminAuthority = Authority.findByAuthority('ROLE_ADMIN') ?: new Authority(authority: 'ROLE_ADMIN').save(flush: true)
def defaultUser = new User(username: "admin", password: "password", accountExpired: false, accountLocked: false,
passwordExpired: false, enabled: true).save(flush: true)
assert defaultUser != null
if (!defaultUser.getAuthorities().contains(userAuthority)) {
UserAuthority.create defaultUser , userAuthority, true
}
if (!defaultUser.getAuthorities().contains(adminAuthority)) {
UserAuthority.create defaultUser , adminAuthority, true
}
assert User.count() == 1
assert Authority.count() == 2
assert UserAuthority.count() == 2
}
def destroy = {}
}
When I start the application it gives me an exception and fails:
Error initializing the application: Cannot invoke method getAuthorities() on null object
So it doesn't create a User instance for some reason (have no idea why).
I'm using default in memory H2 database.
What it can be? I'll really appreciate any help because I've spent a couple of hours on resolving this :(

Reloading Grails Bootstrap with environments

There is a good answer for reloading the Grails Bootstrap in Reloading bootstrap with Grails
But I have environments defined in my init closure and so I get the error:
groovy.lang.MissingMethodException: No signature of method: BootStrap.environments() is applicable for argument types: (BootStrap$_closure1_closure3) values: [BootStrap$_closure1_closure3#19ad0326]
Bootstrap code is basically the spring-security domain classes for role, user, user_role
import org.mine.*
class BootStrap
{
def init =
{ servletContext ->
environments
{
development
{
def adminRole = new DummyRole(authority: 'ROLE_ADMIN').save(flush: true)
def userRole = new DummyRole(authority: 'ROLE_USER').save(flush: true)
def user = new DummyUser(username: 'user1', email_address: 'user1#mine.org', enabled: true, password: 'password')
def user1 = new DummyUser(username: 'user2', email_address: 'user2#mine.org', enabled: true, password: 'password')
def user2 = new DummyUser(username: 'user3', email_address: 'user3#mine.org', enabled: true, password: 'password')
user.save(flush: true)
user1.save(flush: true)
user2.save(flush: true)
DummyUserDummyRole.create manager, adminRole, true
DummyUserDummyRole.create user, userRole, true
DummyUserDummyRole.create user1, userRole, true
DummyUserDummyRole.create user2, userRole, true
assert DummyUser.count() >= 9
assert DummyRole.count() >= 10
assert DummyUserDummyRole.count() >= 9
} // end-development
test {
// bootstrap data for test environment
}
production {
// bootstrap data for production environment
}
}
}
def destroy =
{
// code here
}
}
This works for me:
def servletCtx = org.codehaus.groovy.grails.web.context.ServletContextHolder.servletContext
def myBootstrapArtefact = grailsApplication.getArtefacts('Bootstrap')[-1]
BootStrap.metaClass.environments = grails.util.Environment.&executeForCurrentEnvironment
myBootstrapArtefact.referenceInstance.init(servletCtx)
Lovingly copied (and then modified) from the answer you referenced :-)
I alway used this solution and it worked for me. Works with Grails 3.x too. Here
It is much easier to just swap your syntax to:
Environment.executeForCurrentEnvironment {
production {
// do something in production
}
development {
// do something only in development
}
}

Resources