heroiclabs / nakama

Distributed server for social and realtime games and apps.
https://heroiclabs.com
Apache License 2.0
8.82k stars 1.08k forks source link

Password recovery through email ! #136

Open kageeker opened 6 years ago

kageeker commented 6 years ago

Well i am opening up this issue so you guys would work on a system to make the users able to change their passwords through a confirmation email sent to the users email !

There are many ways to do it , but i think its better to keep it all Server-side . I kinda did most of the work on the client-side (Unity) and the lua module would only update to the DB.

But the basic logic i think is sending a password reset request which would create a random code and store it somewhere in the DB and then email it the user (through a http request to a php mailer), and when the user inputs the correct code he will get redirected to a second page where he could type the new password and send it to the Lua module which would only update the password field.

I know my idea is so basic and i think you guys could do it in a more professional way !

garyforsterio commented 6 years ago

Is there currently any intention to develop this kind of recovery feature?

mofirouz commented 6 years ago

Yep - It will be added within the next 2 releases of Nakama. Nakama won't actually send emails out but will run a Lua script that is responsible for sending emails out (using a third-party service of choice). More detail will be added nearer to the release when all the kinks have been worked out.

garyforsterio commented 6 years ago

Thanks for the quick response @mofirouz. Do you think that will be in the next six months?

mofirouz commented 6 years ago

Yup absolutely - it will most likely be much sooner than that.

CMinch commented 5 years ago

Has this been implemented yet? A link to docs for it here might be helpful since this is #1 hit for "Nakama reset password". Thanks!

novabyte commented 5 years ago

Hey @CMinch. This can be implemented today although isn't as straightforward as we'd like. We will make improvements to support it more clearly.

In the meantime what you can do is create a custom RPC function to initiate the password reset. It will send a link to the user over email (you'd need to use a REST API like Sparkpost) and that link passes the HTTP_KEY and user id (which could be encrypted if you want) as query params. The user can navigate to that HTML page and use the query params to construct a JSON POST request which takes their form value for the new password and submits it with the query params back to the server as another RPC function. This would check the current password and changes it if they match and returns success or failure.

It's admittedly not as "builtin" as it could be but the email sending part will always have to use a separate webservice for email like Mailgun, Sparkpost, or some other.

5un commented 5 years ago

I'm quite interested in this feature as well. Maintaining reset tokens and link sending outside of Nakama should not be too complex. But, I wonder whether there's a way to actually change password through Nakama without fiddling with CockroachDB myself? I see there's some bcrypt hashing done internally, but it wasn't clear to me that there's a runtime code API for it.

novabyte commented 5 years ago

Hey @5un we have the bcrypt util functions to implement this logic as a couple of RPC functions:

https://github.com/heroiclabs/nakama/blob/master/server/runtime_lua_nakama.go#L150

But it would definitely be easier to provide the logic as util functions in both the Lua and Go runtime server APIs. Would be grateful for a pull request? If not we'll see if we can fit this into the next release cycle.

5un commented 5 years ago

@novabyte I see, thanks for pointing out. Unfortunately, we need to stay with Nakama 1.x for some WebGL constraints. I do have a solution for 1.4.3 by extending the session_auth.go, but as there might be no more releases for 1.x, it might not be so useful as a pull request.

mofirouz commented 5 years ago

@5un Ping me over on Gitter (https://gitter.im/heroiclabs/nakama) - we might be able to give you something we've been cooking up as preliminary WebGL support for Nakama 2.

Shelim commented 4 years ago

It is now 2 years later, are there any progress with password recovery?

novabyte commented 4 years ago

@Shelim You're welcome to contribute code to Nakama at any point and we'll prioritize the review on pull requests ahead of the rest of the continuous pipeline of requests we receive.

As far as the feature discussion. We added a way to set a new password in the developer console for a user with the latest 2.8.0 release. It's also entirely possible to solve this issue with a couple of RPC functions which would use an email service with a REST API to enable password resets to be done. You would need to host the html UI for this yourself on an S3/GCS bucket which is quite simple.

nickmarty commented 3 years ago

Needed this as well, took a stab at the implementation. It's using mailgun for sending out emails and you'll need a place to store your html file that the password recovery email will point to. Used S3 for hosting a static webpage with a js file. See the lua file for details.

Don't let the mailgun and S3 scare you, the pricing is literally bare bones but the reliability is top notch. You pay nothing for emails up until a certain threshold and even after how many password resets will you really get 😂

I did a quick cleanup of the setup I use in my production, but forgive me for all the extras in html and js files. You might want to fiddle with the style a bit and add your game icon to both the email and the html endpoint 😉

There are three files in the gist below:

  1. recover_email_password.lua - your password recovery module with further details and actions required;
  2. reset_password.html - your password recovery endpoint, this is where the link in the email should point to;
  3. reset_password.js - javascript that parses the base64 encoded data from the email and submits the new password to nakama. Should be included with reset_password.html at the destination of your choice;

https://gist.github.com/nickmarty/4d348121c164863610cae828bc1c7930

It should be fairly straightforward to use other providers if you wish to do so. Some things could be further optimized for flexibility, html and js could be cleaned up further, well, if you're interested in this you probably know the drill. But it's been tested and it works. Good luck with your projects!

mtalhasaleem502 commented 3 years ago

how can I reset password in Nakama 3.1.0 using GoLang? can I call these functions nk.bcrypt_hash() and nk.sql_exec() in Go lang? Please guide me.

julianeden commented 3 years ago

Really unfortunate that four years later this remains a complicated and undocumented flow -- this API could be as straightforward as client.sendResetPasswordRequest(email) and client.resetPassword(authcode, newEmail) where the authcode is from the reset email. Very reluctant to rely on nakama for user management when something as fundamental as this is still DIY.

novabyte commented 3 years ago

@julianeden Pull requests are always welcome. 👍

champilas commented 3 years ago

Hi everybody! I think I found a walkaround solution for this:

1, you should create and Admin user, as other user, but this will be controlled for you or the game admin.

  1. Everytime you create a new user you should create storage object into the Admin user, for example like this (code for Unity):

    private async Task CreateAdminData(string _email, string _password, string _parentEmail, string _securityKey) { session = await client.AuthenticateEmailAsync("adminmail@example.com", "example1234.", null, false);

    InfoToSaveObject infoTemp = new InfoToSaveObject
    {
        password = _password,
        otherThing1 = _securityKey,
        otherThing2 = false
    };
    
    WriteStorageObject storageObject = new WriteStorageObject
    {
        Collection = "UsersInformation",
        Key = _email, //This is the user email, you need to track it later. 
        Value = JsonUtility.ToJson(infoTemp)
    };
    
    IApiWriteStorageObject[] Objects = { storageObject };
    await client.WriteStorageObjectsAsync(session, Objects);

    }

  2. You create a UI for recover password with the user mail as in Input Field. After this, the code atached to the button could be something like this:

private async Task RecoverPassword(string _email) { session = await client.AuthenticateEmailAsync("adminmail@example.com", "example1234.", null, false);

    StorageObjectId newObject = new StorageObjectId
    {
        Collection = "UsersInformation",
        Key = _email,
        UserId = adminId //This is the admin ID, you got this on Nakama Console
    };

    IApiReadStorageObjectId[] objectsId = { newObject };
    IApiStorageObjects objects = await client.ReadStorageObjectsAsync(session, objectsId);
    IApiStorageObject[] tempData = objects.Objects.ToArray();

    if (tempData.Length != 0)
    {
        InfoToSaveObject tempInfo = JsonUtility.FromJson<InfoToSaveObject>(tempData[0].Value);
        if (!string.IsNullOrEmpty(tempInfo.password))
        {
            EmailSender.instance.SendPasswordEmail(tempInfo.password, _email); //You send an email with password or simply do something
            loadingPanel.SetActive(false);
            verificationPasswordPanel.SetActive(true); //Activate a panel with a notification or do something
            return;
        }
        else
        {
            Error(error, "User not Found"); //notification method
            loadingPanel.SetActive(false);
        }
    }
    else
    {
        Error(error, "User not Found"); //notification method
        loadingPanel.SetActive(false);
    }

}

Maybe is not the best solution, but is working for me in this moment. This could give you guys more ideas. Sorry if my code is not as clean as should be, i just bring my own example as soon as i can before to foget this topic!

As I always say, thanks Nakama Team, you are great!