Grails Spring-Security-Core plugin - Cannot authenticate user - grails

So I am banging my head against the wall trying to get spring-security-core-1.2.7.1 to work with Grails 2.0...
I have looked at the tutorial and run s2. Read that the new plugin encrypts passwords for you, so my bootstrap looks like:
def userRole = Role.findByAuthority('ROLE_USER') ?: new Role(authority: 'ROLE_USER').save(failOnError: true)
def adminRole = Role.findByAuthority('ROLE_ADMIN') ?: new Role(authority: 'ROLE_ADMIN').save(failOnError: true)
def adminUser = User.findByUsername('admin') ?: new User(
username: 'admin',
password: "admin",
enabled: true).save(failOnError: true)
def testUser = User.findByUsername('test') ?: new User(
username: 'test',
password: "test",
enabled: true).save(failOnError: true)
if (!adminUser.authorities.contains(adminRole)) {
UserRole.create adminUser, adminRole
}
if (!testUser.authorities.contains(userRole)) {
UserRole.create testUser, userRole
}
I can look at the H2 database and I see the users, their encoded passwords, see that the roles are created and can see the user role mappings are properly created as well.
However, I still get "Sorry, we were not able to find a user with that username and password." at the login prompt for both users.
I have turned on log4j debug 'org.springframework.security' but all I really get out of the logs is:
2012-01-23 23:08:44,875 ["http-bio-8080"-exec-5] DEBUG dao.DaoAuthenticationProvider - Authentication failed: password does not match stored value

I can't see anything obviously wrong with your code. I'm using the same version of Grails and the spring security plugin, and the following code in Bootstrap.groovy works for me:
def init = { servletContext ->
// create some roles
def userRole = createRole('ROLE_USER')
def adminRole = createRole('ROLE_ADMIN')
// create some users
User admin = createUser('Admin', 'admin#mailinator.com', adminRole)
User user = createUser('User', 'user#yahoo.co.uk', userRole)
}
private User createUser(name, username, role) {
def defaultPassword = 'password'
User user = User.findByUsername(username) ?: new User(
name: name,
username: username,
password: defaultPassword,
passwordConfirm: defaultPassword,
enabled: true).save()
if (!user.authorities.contains(role)) {
UserRole.create user, role
}
user
}
private createRole(String roleName) {
Role.findByAuthority(roleName) ?: new Role(authority: roleName).save()
}

I did have similar issue. Was because I've forgotten to add
grails.plugin.springsecurity.userLookup.userDomainClassName ='yourpackage.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName =yourpackage.UserRole'
grails.plugin.springsecurity.authority.className ='yourpackage.Role'
After that authentication was working.

You can fix the multiple datasources issue by updating the User class.
See https://stackoverflow.com/q/13296594

In the OP's original code, why is the username in single quotes and the password in double quotes. That might be the problem.

Related

Error with constraint ... foreign key in Prod and Test environments. Dev works well. - Grails

I have a system in Grails 2.5.3 and I have problems with the Bootstrap file in test and production environments. In DEV environment the initial data load works perfectly.
Domain class used. SecUser - Spring security
class SecUser implements Serializable {
...
UUID id
Date dateCreated
String username
String password
String email
....
}
Normal user. User:
class User extends SecUser {
UUID id
String name
...
// Relations
static belongsTo = [department:Department]
static hasMany = [evaluations:Evaluation]
}
Evaluation:
class Evaluation {
UUID id
Integer attemptNumber
Date completenessDate
Integer maxAttempt
String testName
Float testScore
// Relations
static belongsTo = [user:User]
}
And I have the following code to load the initial data. It is the same code for all three environments. Dev works well but prod and test show an error.
// Role
def adminRole = new SecRole(authority: 'ROLE_ADMIN')
def userRole = new SecRole(authority: 'ROLE_USER')
// Administrator
def newAdmin = new SecUser(
username: 'admin',
password: 'admin',
email: 'admin#example.com')
// Department
def idDepartment = new Department(name: 'I+D')
// Normal user
def newUser = new User(
username: 'user',
password: 'user',
email: 'user#example.com',
name: 'userTest',
department: idDepartment
)
// Evaluation
def evalUser = new Evaluation(
testName: 'Test example',
attemptNumber: 1,
maxAttempt: 2,
completenessDate: new Date(),
testScore: 7.55,
user: newUser)
// Saving roles
adminRole.save(flush: true, failOnError: true)
userRole.save(flush: true, failOnError: true)
// Saving new admin
newAdmin.save(flush: true, failOnError: true)
// Saving departments
idDepartment.save(flush: true, failOnError: true)
// Saving new users
newUser.save(flush: true, failOnError: true)
// Assign user to role
if (!newAdmin.authorities.contains(adminRole)) {
SecUserSecRole.create newAdmin, adminRole, true
}
if (!newUser.authorities.contains(userRole)) {
SecUserSecRole.create newUser, userRole, true
}
// Saving evaluations - HERE IS THE ERROR
evalUserSTT1.save(flush: true, failOnError: true)
And the error that is displayed only in test and prod environments is the following. I don't know why dev environment doesn't fail and the other environments fails with this violation.
This is due to the fact that in development environment, the datasource config is set to dbCreate = "create-drop" meaning every time you restart the application it drops and then re-creates the database. However in test and production environments are set to dbCreate = "update" where it only updates new changes. Now based on your bootstrap code, you are not checking if an object exists before save hence the bootstrap code will try to create the same roles and users that already exist from first run which causes conflicts.
In summary, modify your bootstrap code to check if records already exist, this is just an example, but will have to do the same for other roles and users etc, e.g.:
def adminRole
def adminRoleExists = SecRole.findByAuthority('ROLE_ADMIN')
if(!adminRoleExists ) {
adminRole = new SecRole(authority: 'ROLE_ADMIN')
adminRole.save(flush: true, failOnError: true)
}

Spring security core plugin for grails - Not able to access RequestMap parameters from the database

I have installed grails Spring security core plugin with RequestMap to retrieve URL from the database. I assume I have setup everything as its mentioned in the guide. When I start my application(http://localhost:8080/scadmin/index/) I get 'sorry, you are not authorized to view this page'. The admin user authenticated properly but RequestMap isnt allowing me to access the url. What's that I am doing wrong? please help.
config.groovy
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.tx.sc.auth.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.tx.sc.auth.UserRole'
grails.plugin.springsecurity.authority.className = 'com.tx.sc.auth.Role'
grails.plugin.springsecurity.requestMap.className = 'com.tx.sc.auth.Requestmap'
grails.plugin.springsecurity.securityConfigType = 'Requestmap'
My controller -
class AdminController {
def index() {
List<Portal> pList = portalService.listAllPortalInfo()
render(view: "admin", model:[portalList:pList])
}
}
Setting Role
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
Admin User
def adminUser = new User(username: 'admin', password: '12345',email: 'admin#abc.com',enabled: true, accountLocked: false, accountExpired: false, passwordExpired: false).save(flush: true)
Map user and role-
if (!adminUser.authorities.contains(adminRole)) {
UserRole.create(adminUser, adminRole, true)
}
RequestMap-
new Requestmap(url: '/scadmin/admin/index', configAttribute: 'ROLE_ADMIN').save(flush: true)
/scadmin/admin/index should be /admin/index - don't include the context.

How to add a User in Grails Bootsrap with Audit Trails on?

Hi I'm having a hard time trying to add the first user in my grails bootstrap. I've tried many different ways but all have failed since the Audit Trail plugin wants a user to stamp the createdBy and EditedBy fields but the first one doesn't exit yet.
Here is my config for Audit Trails, essentially it's the same as default except I'm using User.username over the User.id:
grails {
plugin {
audittrail {
createdBy.field = "createdBy"
createdBy.type = "java.lang.String" //Long is the default
editedBy.field = "editedBy"
editedBy.type = "java.lang.String" //Long is the default
createdDate.field = "createdDate"
editedDate.field = "editedDate"
currentUserClosure = {ctx->
def authPrincipal = ctx.springSecurityService.principal
if(authPrincipal && authPrincipal != "anonymousUser"){
return authPrincipal.username
} else {
return null //fall back
}
}
}
}
}
Here is what my User class looks like, ie. I just add the annotation for the plugin to work:
#gorm.AuditStamp
class User {
//... basic Spring Security Generated User File with minor changes
}
Here is the contents of my bootstrap file:
def adminUser = new User(
username: 'admin',
enabled: true,
password: 'password',
firstName: 'ADMIN',
lastName: 'ADMIN'
).save(flush: true)
// The below will work if I take off the annotation on User class.
SpringSecurityUtils.doWithAuth('admin') {
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
UserRole.create adminUser, adminRole, true
}
So now how can I add that first user? I've tried:
- Using annonymousUser
- Failed, plugin prevents it
- Hardcoding the createdBy and editedby to "admin"
- Failed get's overridden
- Use executeUpdate to insert the user directly in the DB
- Failed: in bootstrap
- Delay the save of the first user until the doWithAuth
- Failed: couldn't find the user
Any help would be great! Thanks!
I had the same problem and was searching for a solution. I managed to get it working by doing the below:
grails {
plugin {
audittrail {
createdBy.field = "createdBy"
createdBy.type = "java.lang.String" //Long is the default
editedBy.field = "modifiedBy"
editedBy.type = "java.lang.String" //Long is the default
createdDate.field = "createdDate"
editedDate.field = "modifiedDate"
//custom closure to return the current user who is logged in
currentUserClosure = {ctx->
//ctx is the applicationContext
def userName = ctx.springSecurityService.principal?.username
return userName != null ? userName : "System"
}
}
}
}
In the Bootstrap.groovy file, just do a save like:
def adminUser = new User(username: 'admin', enabled: true, password: 'password',
firstName: 'ADMIN', lastName: 'ADMIN').save(flush: true)
def adminRole = new Role(authority: 'ROLE_ADMIN').save(flush: true)
UserRole.create adminUser, adminRole, true
The newly created first user will be stamped with user "System" (createdBy and modifiedBy columns).

spring security core grails not logging in

Installed Spring Security Core as plugin then did quickstart
Here is my User domain class
package auth
class User {
def springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static mapping = {
// password is a keyword in some sql dialects, so quote with backticks
// password is stored as 44-char base64 hashed value
password column: '`password`', length: 64
}
static constraints = {
username blank: false, size: 1..50, unique: true
password blank: false, size: 8..100
}
Set getAuthorities() {
UserRole.findAllByUser(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected encodePassword() {
password = springSecurityService.encodePassword(password, username)
}
}
And my boostrap.groovy is
class BootStrap {
def init = { servletContext ->
auth.User james = new auth.User(username: 'test', enabled: true, password: 'password')
james.save()
if (james.hasErrors())
{
println("he has errors")
}
println("we made it! ")
}
def destroy = {
}
}
But when I go to login, it keeps saying "Sorry, we were not able to find a user with that username and password." Any thoughts?
This is because you are using the salt while encoding the password.
password = springSecurityService.encodePassword(password, username)
I have no idea of salting and hence can not guide you to much.
But if you encode your password without salting then your code works, just remove username when encoding the password, try this
password = springSecurityService.encodePassword(password)
Hope this helps.
If you create the user in BootStrap.groovy, try changing this:
def adminUser = User.findByUsername('admin') ?: new User(
username: 'admin',
password: springSecurityService.encodePassword('admin'),
enabled: true).save(failOnError: true)
to this:
def adminUser = User.findByUsername('admin') ?: new User(
username: 'admin',
password: 'admin',
enabled: true).save(failOnError: true)
The problem is that you are using the encoding password twice, once in the Domain and once in the constructor's parameters.
Can you validate that the user is actually bootstrapped into the database?
If so, I ran into a similar issue with Tomcat caching some data incorrectly.
Here is what I did:
Stopped Tomcat
Deleted all the files in Tomcat's Temp directory
Restarted Tomcat
After that, it worked fine.
Let me know if this helps.
Also, its been a while since I've built a Grails site from scratch, but I think I remember there being an issue with some online instructions. SpringSecurity might be encoding the password for you, so when you do it, it is getting double encoded.
Try removing the lines that encode the password.

Grails 2.1.1 and Spring Security Core plugin

I've been noticing that a lot of the tutorials I'm following use this:
def springSecurityService
and since I want to get records only by current logged in user I use:
def user = params.id ? User.findByUserId(params.id) : User.get(springSecurityService.principal.id)
and also in my Bootstrap I want to create a username and password, so for instance
def user = new User(
username: username,
password: springSecurityService.encodePassword("tops3kr17"),
enabled: true)
However I noticed that the password is not being created, and Spring Source Tools does not find the method .principal.id or .encodePassword (they stay underlined in STS) and wants to use SpringSecurityService with a capital S when hitting CTL+SPACE (and doesn't complete .principal.id or .encodePassword).
So i'm a little lost because it seems that the tutorials are out of date
So how can I do what I described with what the current supported methods are? Or am I missing something really simple? : )
class BootStrap {
def springSecurityService
def init = { servletContext ->
def demo = [
'jack' : [ fullName: 'Jack Demo Salesman'],
'jill' : [ fullName: 'Jill Demo Saleswoman']]
def now = new Date()
def random = new Random()
def userRole = SecRole.findByAuthority("ROLE_SALES") ?: new SecRole(authority: "ROLE_SALES").save()
def adminRole = SecRole.findByAuthority("ROLE_ADMIN") ?: new SecRole(authority: "ROLE_ADMIN").save()
def users = User.list() ?: []
if (!users) {
demo.each { username, password, userAttrs ->
def user = new User(
username: username,
password: springSecurityService.encodePassword('secret'),
enabled: true)
if (user.validate()) {
println "DEBUG: Creating user ${username}..."
println "DEBUG: and their password is ${password}"
user.save(flush:true)
SecUserSecRole.create user, userRole
users << user
}
else {
println("\n\n\nError in account bootstrap for ${username}!\n\n\n")
user.errors.each {err ->
println err
}
}
Using the injected instance of SpringSecurityService is the right approach.
def springSecurityService
def foo() {
springSecurityService.principal
springSecurityService.encodePassword('fdsfads')
....
}
If the IDE isn't recognizing it, there is an issue with your IDE.

Resources