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
Related
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
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.
I am using Grails 3.0.9
application.yml:
hibernate:
cache:
queries: false
use_second_level_cache: true
use_query_cache: false
region.factory_class: 'org.hibernate.cache.ehcache.EhCacheRegionFactory'
endpoints:
jmx:
unique-names: true
dataSource:
pooled: true
jmxExport: true
driverClassName: com.mysql.jdbc.Driver
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
username: root
password: 123
environments:
development:
dataSource:
dbCreate: update
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/blereview?useUnicode=true&characterEncoding=UTF-8
on grails run-app no errors on console but no table is created in the database.
Domain class I am using
DataRequest {
String token;
static constraints = { }
}
On windows,one of my friend is also facing same issue.He fixed it by setting GRAILS-HOME using cygwin(grails run-app from cygwin) and it works for him.
Hope it helps you.
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.
I have recently attempted to create an application that allows me to compare 3 separate databases for their values. The databases are 3 Oracle instances which house (essentially) the same database, but in a DEV/TEST/PROD setting.
What I want to do is create one Domain class in GRAILS 3. I then want to be able to fetch the records which that domain class maps to, but do it for all 3 environments.
From reading the Grails 3 docs, it looks like this should be possible by defining 3 datasources in application.yml (in my example here I define 4):
dataSources:
dataSource:
pooled: true
jmxExport: true
logSql: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#someserver:1521:DEV1
dataSource1:
pooled: true
jmxExport: true
logSql: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#someserver:1521:DEV1
dataSource2:
pooled: true
jmxExport: true
logSql: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#someserver:1521:TEST1
dataSource3:
pooled: true
jmxExport: true
logSql: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#someserver:1521:PROD1
and then within the domain class' mapping specifying datasources in the mapping:
package plsutils
class DmjTypes {
String code
String description
Date insertDate
String insertUser
Date modifyDate
String modifyUser
String dbEnv
static mapping = {
datasources(['dataSource1', 'dataSource2', 'dataSource3'])
version false
table name: "CDE_DMJ_TYPES", schema: "MYSCHEMA"
id generator: 'sequence' ,params:[sequence: 'DMJTY_SEQ']
columns {
id column: "DMJTY_ID"
code column: "DMJTY_CDE"
description column: "DMJTY_DESCR"
insertDate column: "INSERT_DTT"
insertUser column: "INSERT_USER"
modifyDate column: "MODIFY_DTT"
modifyUser column: "MODIFY_USER"
dbEnv formula:'( select inst.instance_name || \'-\' || inst.host_name from v$instance inst ) '
}
}
}
and then, within my controller, I should be able to do something like this:
params.max = Math.min(max ?: 10, 100)
dmjTypesListDev = DmjTypes.dataSource1.list(params)
dmjTypesListTest = DmjTypes.dataSource2.list(params)
dmjTypesListProd = DmjTypes.dataSource3.list(params)
I am getting an error upon the first call:
URI /dmjTypes/index
Class groovy.lang.MissingPropertyException
Message null
Caused by No such property: dataSource1 for class: plsutils.DmjTypes
I'm using ojdbc7.jar, connection to Oracle 11g and I'm using Grails 3.0.9.
I can't help but think I'm doing something subtly stupid somewhere. Can anyone please help me with this?
Cheers,
Allen
Basing on official documantation try dataSources keyword:
dataSources:
dataSource:
pooled: true
jmxExport: true
driverClassName: org.h2.Driver
username: sa
password:
lookup:
dialect: org.hibernate.dialect.MySQLInnoDBDialect
driverClassName: com.mysql.jdbc.Driver
username: lookup
password: secret
url: jdbc:mysql://localhost/lookup
dbCreate: update
environments:
development:
dataSources:
dataSource:
dbCreate: create-drop
url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
test:
dataSources:
dataSource:
dbCreate: update
url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
production:
dataSources:
dataSource:
dbCreate: update
url: jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
properties:
jmxEnabled: true
initialSize: 5
…
lookup:
dialect: org.hibernate.dialect.Oracle10gDialect
driverClassName: oracle.jdbc.driver.OracleDriver
username: lookup
password: secret
url: jdbc:oracle:thin:#localhost:1521:lookup
dbCreate: update
Once I corrected the version of grails referred to in the gradle.properties and performed a complete clean and rebuild, I was able to get it working. I believe all my issues were because of a version mismatch of the grails I was using to build it.
So, this is the appropriate datasource entry:
dataSources:
dataSource:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#somelocalserver:1521:LOCAL
one:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#somedevserver:1521:DEV1
two:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#sometestserver:1521:TEST1
three:
pooled: true
jmxExport: true
driverClassName: oracle.jdbc.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#someproductionserver:1523:PROD1
This is the working domain class:
class DmjTypes {
String code
String description
Date insertDate
String insertUser
Date modifyDate
String modifyUser
String dbEnv
static mapping = {
datasources(['one', 'two', 'three'])
version false
table name: "CDE_DMJ_TYPES", schema: "MYSCHEMA"
id generator: 'sequence' ,params:[sequence: 'DMJTY_SEQ']
columns {
id column: "DMJTY_ID"
code column: "DMJTY_CDE"
description column: "DMJTY_DESCR"
insertDate column: "INSERT_DTT"
insertUser column: "INSERT_USER"
modifyDate column: "MODIFY_DTT"
modifyUser column: "MODIFY_USER"
dbEnv formula:'( select inst.instance_name || \'-\' || inst.host_name from v$instance inst ) '
}
}
}
Try this:
dataSources:
dataSource:
pooled: true
jmxExport: true
logSql: true
driverClassName: oracle.jdbc.driver.OracleDriver
username: MYUSER
password: Password1
dbCreate: validate
autoReconnect: true
#url: jdbc:oracle:thin:#someserver:1521:DEV1(I remember in 3.0.9 this is under environments:development:dataSources:dataSource)
dataSource2:
pooled: true
jmxExport: true
logSql: true
driverClassName: oracle.jdbc.driver.OracleDriver
dialect: org.hibernate.dialect.OracleDialect
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#someserver:1521:TEST1
autoReconnect: true
dataSource3:
pooled: true
jmxExport: true
logSql: true
driverClassName: oracle.jdbc.driver.OracleDriver
dialect: org.hibernate.dialect.OracleDialect
username: MYUSER
password: Password1
dbCreate: validate
url: jdbc:oracle:thin:#someserver:1521:PROD1
autoReconnect: true
In controller:
static mapping = {
datasources(['dataSource', 'dataSource2', 'dataSource3'])
.....
}