How do I encrypt a string in a Grails domain class? - grails

For example, I created this domain class:
package loginproject
class User {
String name
String password
Boolean state
static constraints = {
}
}
I think it is a good idea to encrypt the password string but I do not know where to start. What algorithm? What do I need to do?

If you need a complete authentication and authorization solution +1 for spring security core plugin. If you just want to encrypt a domain class or parts of it in the DB, go for http://www.grails.org/plugin/crypto.

You can utilize a plugin, such as Spring Security core plugin. And actually, we often save password hash instead of its encryption.

Related

spring security: what's the best practice for include value in permission?

In spring security, or RBAC, the Authority is described as a string, such as "download-file" means user can download file. If I need to limit user maximum daily download times and assign different values to different user, means the Authority contains dynamic values, how can I do this in spring security?
As you are alluding to there is a difference between authorities (i.e. roles) and permissions. Authorities tend to broadly apply for an application and have no state while permissions tend to be on specific objects and contain state.
This seems more like a domain problem than a permissions problem. Putting the logic into security feels a bit like having a form that must contain a valid email and checking the email format in security. I'd consider moving the logic outside of the security code.
If you really want to do this with Spring Security, I'd use a custom Bean that performs the check:
#Component
public class Download {
public boolean isAlowedForUser(Authentication authentication) {
// ...
return result;
}
public boolean isAllowedForCurrentUser() {
return isAllowedForUser(SecurityContextHolder.getContext().getAuthentiation());
}
}
Then you can autowire the Bean into your code and check the permission by invoking the code. If you prefer, you can also integrate into Spring Security's method security to perform the checks. To enable it you need to specify #EnableGlobalMethodSecurity(prePostEnabled = true) at the top of one of your configuration classes. Then you can use something like this on a Spring managed Bean:
#PreAuthorize("#download.isAllowedForCurrentUser()")
public void downloadFile(String fileName) {
Please refer this link
Spring Boot : Custom Role - Permission Authorization using SpEL
You can add new permission , like "DOWNLOAD_FILE" and authenticate if the current user has that permission using -
#PreAuthorize("hasPermission('DOWNLOAD_FILE')")
You can also limit access for Roles as well
#PreAuthorize("hasRole('ADMIN') and hasPermission('DOWNLOAD_FILE')")

Jasypt encrypted field and Criteria API not getting results (Grails)

I just started playing with Grails and working on simple registration/login feature.
I have this simple domain object:
class Person {
String firstName, lastName, email
String login, password
static constraints = {
firstName nullable: true
lastName nullable: true
}
static mapping = {
password type: GormEncryptedStringType
}
}
I am saving Person object just fine. But then when I try to retrieve it for login purposes using Criteria API, it won't find it:
def criteria = Person.createCriteria()
def person = criteria.get {
and {
eq("login", params.login)
eq("password", params.password)
}
}
If I remove eq("password", params.password) or change it to something not encrypted it works just fine. Anyone have an idea how to handle that?
You're doing it wrong (security). You don't encrypt passwords, you hash them. Hashing is one-way and lossy, whereas encryption is two-way and lossless, but if you can decrypt the passwords then you're vulnerable to attackers who gain access to the decryption keys, and then they'll be able to decrypt them too.
If you use hashing, then you can (but of course shouldn't) let anyone view the hashed passwords because they're useless if you use a good hashing scheme. Bcrypt is one of the best and is easy to use.
Instead of decrypting the stored encrypted password to verify a cleartext password from a user authentication attempt, you should hash the supplied password and validate it against the stored hashed password. For some algorithms this is a simple as checking that the values are the same, but that's not the case with Bcrypt since the algorithm always generates a different hash for each invocation. But the algorithm can validate two hashed passwords, so that's not a problem.
So the real fix to your problem is to stop using encryption, and stop 'rolling your own' security. spring-security-core is a popular option.

Why must I store a password column in my User domain if I'm using LDAP authentication?

I have a Grails application that uses the Spring Security Core and Spring Security LDAP plugins. I am using the bind method of authentication with an LDAP server as my only authentication provider. Why must I still store a password column in my database? My application has absolutely no need to store a value for a password, but it will not work if I remove the password field from the generated User domain class. Do I really have to store a password column with the value of null in my User table? Surely there must be a different approach to this.
I don't think you must!
simply define the password field as transient in your UserAccount class:
class UserAccount {
String password
static transients = [ 'password' ]
}

Spring security 3.1.4 and ShaPasswordEncoder deprecation

Today I upgraded the spring security version of the application I'm working on from 3.1.3 to 3.1.4, and I noticed a deprecation warning on the org.springframework.security.authentication.encoding.ShaPasswordEncoder class.
So I switched to the new org.springframework.security.crypto.password.StandardPasswordEncoder implementation.
I had it working and I'm able to register a new user and login in my application, but, as I feared, I'm not able to login using passwords generated with the previous ShaPasswordEncoder and my custom salt.
Since I have a database with many users already registered, what should I do to switch implementation without invalidating the old encoded passwords?
Is it even possible?
See also: How to use new PasswordEncoder from Spring Security
If you want to switch to a more secure password encoding mechanism, then I would recommend you use BCrypt. I would use something like this to migrate your users:
// Implement the old PasswordEncoder interface
public class MigrateUsersPasswordEncoder implements PasswordEncoder {
#Autowired
ShaPasswordEncoder legacyEncoder;
#Autowired
JdbcTemplate template;
BCryptPasswordEncoder bcryptEncoder = new BCryptPasswordEncoder();
#Override
public String encodePassword(String rawPass, Object salt) {
return bcryptEncoder.encode(rawPass);
}
#Override
public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
if (legacyEncoder.isPasswordValid(encPass, rawPass, salt)) {
template.update("update users set password = ? where password = ?", bcryptEncoder.encode(rawPass), encPass);
return true;
}
return bcryptEncoder.matches(rawPass, encPass);
}
}
You can check what proportion of users have been migrated by the format of the password field. BCrypt strings have a distinctive syntax beginning with a $ sign.
One of the other answers points out that this code could accidentally update multiple passwords at the same time. The question stated that a custom salt was being used, so the chance of collisions is negligible if the salt is randomly chosen, but this might not always be the case. If two passwords were updated, what would the problem be? It would then be possible to detect that accounts have the same password from the bcrypt hashes. That's the case anyway since it requires that the SHA hashes were the same for the update to occur. If you think it might be a problem (e.g. because of poor salt choice or even the use of unsalted hashes) it would be trivial to modify the SQL to detect this and perform multiple updates with separate BCrypt hash values.
I tried to add a comment to the accepted answer, but alas, I don't have enough cred yet. :(
I believe the accepted answer's code snippet is potentially dangerous where it updates the password in the database. If the ShaPasswordEncoder produces the same results when encrypting (which is why the assumption is being made that the old password can be found, and I verified this is definitely true at least with a null salt on the ShaPasswordEncoder), you still cannot guarantee that the password is unique amongst all users. You could, by chance, share the same password as another user on the system, and that SQL code would end up changing all users that happen to have your password.
I think the safest strategy is to not update the user's password, and instead provide a migration strategy that plans for the eventual removal of the ShaPasswordEncoder.
Use the provided example code.
Remove the code that updates the database.
Add a feature like, "Forgot your password" or "Generate a new password" to handle the eventual case of users not having created a new password when the ShaPasswordEncoder is removed. Like either when you upgrade to Spring Security that has it removed, or choose to remove it yourself.
Update your documentation or make it clear that in the next major release version of the software, that users will have had to re-save their passwords or will have to use the before-mentioned password reset feature.
Give the user the grace period of a major version release cycle to transition (they probably won't do it and just get caught in the reset password).
That's an excellent question and am looking forward to reading some answers.
AFAIK it's impossible to do in a single mass update: you just can't retrieve the original string from a hash. You would have to check during a login attempt if the submitted password matches either strategy and convert it to the new strategy if necessary, but that means you would have to live with both encoding strategies until all users have logged in and hence all passwords have been converted. Not very convenient nor necessarily intuitive for new developers coming on board.
I move to implement class PasswordEncoder
org.springframework.security.crypto.password.PasswordEncoder
This solution help me to fixed deprecated PasswordEncoder.
Code:
public class LegacySupportPasswordEncoder implements PasswordEncoder {
private final BCryptPasswordEncoder bcryptEncoder;
private final JdbcTemplate jdbcTemplate;
#Autowired
public LegacySupportPasswordEncoder(#Qualifier("passwordEncoder") final BCryptPasswordEncoder bcryptEncoder,
final RoutingDataSource dataSource) {
this.bcryptEncoder = bcryptEncoder;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
#Override
public String encode(CharSequence rawPassword) {
return this.bcryptEncoder.encode(rawPassword);
}
#Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
//Your code validate credential in database here
return this.bcryptEncoder.matches(rawPassword, encodedPassword);
}
}

Spring Security 3 + Random Salt

So I understand that you can check a password in Spring Security with salt based on a userDetail property and then hash it to compare to a hash in the database, however what if the salt used when creating each user is random (and is stored in the DB), would I need to create my own userDetails class that contains a salt property and then set that as the field spring security uses to salt with in the securityApplicationContext?
If so how would I go about writing my own userDetails class to accomplish that? Sorry still pretty new to Spring/Java.
Ok but then how do I tell the securityApplicationContext to use myCustomUserDetails class to store the user instead of the default userDetails class?
Like this:
<b:bean id="customUserDetailsService" class="com.your.company.security.MyUserDetailsService"/>
<s:authentication-provider user-service-ref="customUserDetailsService" />
This goes in your security context.
Also this might help.
Writing a custom UserDetailsService.

Resources