joscha / play-authenticate

An authentication plugin for Play Framework 2.x (Java)
http://joscha.github.com/play-authenticate/
Other
807 stars 366 forks source link

Forcing password change on first login? #307

Open slimandslam opened 8 years ago

slimandslam commented 8 years ago

I'd like to implement a feature where the user must change their password when they first login. To do that, it appears that I need to change a method that is within the Play-Authenticate jars:

What I'd like to do is have a new login result:

LoginResult.USER_NEEDS_TO_CHANGE_PASSWORD

And then have a corresponding action that displays the password change form. The main changes would go in the MyLoginUsernamePasswordAuthUser routine.

Is there a recommended way of doing this?

protected com.feth.play.module.pa.providers.password.UsernamePasswordAuthProvider.LoginResult
loginUser( final MyLoginUsernamePasswordAuthUser authUser) {
                final User u = User.findByUsernamePasswordIdentity(authUser);

                        if (u.changePassFirstTime) {
                                return
LoginResult.USER_NEEDS_TO_CHANGE_PASSWORD;
                        }
joscha commented 8 years ago

The easiest way I can see this being done OOTB is changing the password to something random at signup that the user doesn't know, changing the verification email text and include a link to the forgot password page (which would be named 'set password').

slimandslam commented 8 years ago

In our version, we're not using email for signup. There's already an "admin" panel where an administrator can assign a password to a user. The admin gives the password to the user (via email) and the user logs in and immediately has to change the password. So, your suggestion doesn't really work.

joscha commented 8 years ago

You could use a deadbolt overlay to check whether the password has been changed (similar to a restricted page) and if not, show an according flash message or redirect to the password change page.

slimandslam commented 8 years ago

Are there any examples of "deadbolt overlays" in github or elsewhere?

slimandslam commented 8 years ago

If I could change this routine here:

if (payload == Case.LOGIN) {
            final L login = getLogin(context);
            final UL authUser = buildLoginAuthUser(login, context);
            final LoginResult r = loginUser(authUser);
            switch (r) {
            case USER_UNVERIFIED:
                // The email of the user is not verified, yet - we won't allow
                // him to log in
                return userUnverified(authUser).url();
            case USER_LOGGED_IN:
                // The user exists and the given password was correct
                return authUser;
            case WRONG_PASSWORD:
                // don't expose this - it might harm users privacy if anyone
                // knows they signed up for our service
            case NOT_FOUND:
                // forward to login page
                return onLoginUserNotFound(context);

And add a case PASSWORD_CHANGE_ON_FIRST_LOGIN then I could do it.

That's deep inside your plugin in the file: play-authenticate/code/app/com/feth/play/module/pa/providers/password/UsernamePasswordAuthProvider.java

joscha commented 8 years ago

Deadbolt is used for the normal restricted pages, it should work the same way. The code you are looking at is being subclassed in My... in the sample. If you can implement it there, it would be best I think.

slimandslam commented 8 years ago

How do I create a new LoginResult, for example:

return LoginResult.USER_NEEDS_PASSWORD_RESET;

That's connected to a method call like this:

    @Override
        protected Call userNeedsPassReset(final UsernamePasswordAuthUser authUser) {
                return routes.Account.changePassword();
        }
joscha commented 8 years ago

You might need to refactor play-authenticate a little bit - if it is in line with the rest of the functionality, we can merge it back after!

slimandslam commented 8 years ago

Humor me a bit here. I'm running Play 2.4.6, and in my build.sbt file, I have:

"com.feth" %% "play-authenticate" % "0.7.0"

If I make changes to the source of the plugin, how do I tell Play to use my code instead of pulling play-authenticate from the repo?

joscha commented 8 years ago

There are some comments in the sample project (play-authenticate-usage), I think in build.sbt and plugins.conf that say "Uncomment this for local dev" or "Comment this for local dev" - you'd need to do the same thing in your application.

slimandslam commented 8 years ago

To do local development of the v0.7.0 code using Play 2.4.6, I had to uncomment the "local development" lines in the build.sbt and plugins.sbt files, and then move the plugin code into the directory modules/play-authenticate where the modules directory is in the same directory as my build.sbt file. I also had to delete the "release.sbt" file in the play-authenticate repo as that file causes errors and seems to have no role in the dev process.

slimandslam commented 8 years ago

Is Matthias - @mkurz - looking at this issue? I'd like to discuss it with you, if possible.

mkurz commented 8 years ago

@slimandslam Yes I am here - but I didn't follow this conversation. I just had a quick read now.

mkurz commented 8 years ago

@slimandslam Is it possible for you to upgrade your app to use Play 2.5?

slimandslam commented 8 years ago

Hi @mkurz, we can, but we don't have time right now. We're going to be on v2.4.6 for at least a few more months. Is there a way for me to contact you offline?

mkurz commented 8 years ago

I am very busy right now as well so I don't know If I can help you straight away.