question

Darius Vu avatar image
Darius Vu asked

How to build a custom server to the PlayFab Admin API - Reset Password?

Dear support team,

I am trying to develop the "Reset password" function in my app. I am following the steps in this post to do it.

https://community.playfab.com/questions/44554/how-to-make-the-reset-password-function.html

Currently, I completed the steps as below:

- Write a custom CloudScript function -- "storeToken", to save the Token to the player's internal data.

- Create a PlayFab Rule to store the token to the player's internal data when users click on "confirmationURL" in the confirmation email

- Design the UI in my app that users can write new password and send the request to change their password.

But now I am facing the problem is that to call Reset Password that is only called by PlayFab Admin API.

https://docs.microsoft.com/en-us/rest/api/playfab/admin/account-management/resetpassword?view=playfab-rest

So now I want to make a custom server to receive request from users and call the API - Reset Password. I spent a lot of time on searching and investigating, and know how to build the custom server as these references :

- https://docs.microsoft.com/en-us/gaming/playfab/features/multiplayer/servers/custom-game-servers

- https://github.com/PlayFab/PlayFabGameServer

However, I don't know how to make the Game Server in Unity to receive request from users and call the API - Reset Password using the store Token that is saved as the player's internal data and new password. And how to send the request from clients (my app) to a custom server to make the reset password?

Could you give me the example code for that in details?

This issue is really important for me.

And I hope that the API - Reset Password will be implemented by Client API in the future, it is easy for developers.

Thank you so much for your support.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Citrus Yan avatar image
Citrus Yan answered

@Luc Vu

[Edited]

Here is the sample code that depicts the basic flow, for your reference:

using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using PlayFab.AdminModels;
namespace PlayFab.Samples
{
    public static class ResetPassword
    {
        [FunctionName("ResetPassword")]
        public static async Task<dynamic> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation($"{nameof(ResetPassword)} C# HTTP trigger function processed a request.");
            
            
            FunctionExecutionContext<dynamic> context = JsonConvert.DeserializeObject<FunctionExecutionContext<dynamic>>(await req.ReadAsStringAsync());
            dynamic args = context.FunctionArgument;
            var newPassword = args["newPassword"]; // retrieve the new password sent by the client, specified in ExecuteFunction -> FunctionParameter -> newPassword

            //set up title id and secret key for admin api to use 
            var adminApiSettings = new PlayFab.PlayFabApiSettings()
            {
                TitleId = Environment.GetEnvironmentVariable("PlayFab.TitleId", EnvironmentVariableTarget.Process),
                DeveloperSecretKey = Environment.GetEnvironmentVariable("PlayFab.TitleSecret", EnvironmentVariableTarget.Process),
            };
            
            var adminAPI = new PlayFabAdminInstanceAPI(adminApiSettings);

            //get player's token stored in internal data
            var getUserInternalDataResponse = await adminAPI.GetUserInternalDataAsync(new AdminModels.GetUserDataRequest(){
                PlayFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId,
                Keys = new List<string> () {"Token"}
            });

            var tokenId = getUserInternalDataResponse.Result.Data["Token"].Value;
            //reset the password
            return await adminAPI.ResetPasswordAsync(new AdminModels.ResetPasswordRequest() {
                Password = newPassword,
                Token = tokenId
            });
        }
    }
}
19 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Darius Vu avatar image Darius Vu commented ·

Hi @Citrus Yan

I referred your code to publish the function "ResetPasword" in Azure and register this function in Playfab.

However, after running, I got the error as below: "ErrorCode": "CloudScriptAzureFunctionsHTTPRequestError",

I set Function URL by click and copy the Function URL in HTTP function. For FunctionExecutionContext, I add the CS2AFHelperClasses.cs in here:

https://github.com/PlayFab/PlayFab-Samples/blob/master/Samples/CSharp/AzureFunctions/CS2AFHelperClasses.cs

Or I use FunctionContext from PlayFab.Plugins.CloudScript then it also has the same issue as above.

In the client, I set the function parameter of ExecuteFunction as below.

FunctionParameter = new Dictionary<string, object>() { { "newPassword", newPassWord } },

Do you know why and how to fix it?

I am grateful so much for your support!!!

0 Likes 0 ·
capture.png (42.2 KiB)
Citrus Yan avatar image Citrus Yan Darius Vu commented ·

Just found a problem in the code I provided above, in line 37, it should be

PlayFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId,

otherwise it will return null reference.

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

Hi Citrus Yan,

Thank you so much for your help.

I tried to change following that, and re-upload the function to Azure but it still got the same issue. :(

Could you help me again?

0 Likes 0 ·
Darius Vu avatar image Darius Vu Darius Vu commented ·

Hi Citrus Yan,

Yes, I will try to debug the code by showing the logs on this. Thank you for your help!!!!

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

Although the trigger action is executed successfully to store the token. You can see the picture below.

0 Likes 0 ·
issue.png (41.3 KiB)
Citrus Yan avatar image Citrus Yan Darius Vu commented ·

Please open the Azure Function steaming log and identify which issue did the code run into.

1 Like 1 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

And this is the log issue in Unity Client:

0 Likes 0 ·
issue1.png (26.2 KiB)
Darius Vu avatar image Darius Vu Citrus Yan commented ·

Hi Citrus Yan,

Finally, it is working and I can reset the password in the client.

The reason is that both TitleId and DeveloperSecretKey values are null. I fixed it by assigning directly my TitleId and DeveloperSecretKey value. Then it is working well. :)

I am so grateful for your support continuously!!!

Again, thank you so much!!!

0 Likes 0 ·
Citrus Yan avatar image Citrus Yan Darius Vu commented ·

Great! Happy to help:)

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

Hi @Citrus Yan

I also have one problem that when I call the function - ExecuteFunction to reset password when users forgot their password.

To call this function, users have to login first, do you have any suggestion for me in the case when an user forgot the password and want to reset it by email?

Thank you so much!

,

0 Likes 0 ·
Citrus Yan avatar image Citrus Yan Darius Vu commented ·

Ah, that's a tricky one, you'd need to have the user remember the token in the redirect URL so that they can type in both the token and their new password in the Unity Client and directly calls a Azure Function that calls ResetPassword to have their password reset. The key is that the user must know their password-reset token.

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

@Citrus Yan: But in that way, how the Unity client can call the Azure Function without login?

Because the ExecuteFunction in Playfab Cloud Script need to login first as the code below. If we can execute function in Cloud Script without login is the best way.

if (!context.IsEntityLoggedIn()) throw new PlayFabException(PlayFabExceptionCode.NotLoggedIn,"Must be logged in to call this method");<br>

But I am trying to do it in this way:

- When user click "forgot password" -> send the email verification.

- When user click "URL confirmation" in the email -> store "Token" and run Azure function "Reset Password" with the temporary password.

- User can login with the temporary password and change the password later by executing function in Cloud Script.

However, I am facing the issue that cannot get the Playfab ID in Azure function although I tried both ways as below.

PlayFabId = context.CallerEntityProfile.Entity.Id,
PlayFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId

Do you know how to get Playfab ID in Azure function without login?

Many thanks.

0 Likes 0 ·
Citrus Yan avatar image Citrus Yan Darius Vu commented ·

I meant calling Azure Function directly, not through ExecuteFunction. And, use temporary password won't work since the token can only be used once.

WIthout login, there is no way for Azure Function to know who the caller is, therefore there is no context provided.

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

As I see, the cloud script can get currentPlayerId to store the Token, but is there no way to get currentPlayerId from Azure function?

And do you have any idea to get the Token and run it in cloud script? I think that it is hard for users if we require them to type the Token, right? And remember the Token is also the problem. :(

0 Likes 0 ·
capture6.png (35.2 KiB)
Citrus Yan avatar image Citrus Yan Darius Vu commented ·

If the Azure Function is called with ExecuteFunction by a logged in user, then the PlayFabId can be retrieved via context.CallerEntityProfile.Lineage.MasterPlayerAccountId. However, I was talking about calling the Azure Function directly without player logged in, in that case, type in the token would be the only way to identify the player.

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

@Citrus Yan: In this way, do you know any way to get and send the token by email after users click on "URLConfirmation" in the email verification? or display the Token for users type it in the app?

0 Likes 0 ·
Citrus Yan avatar image Citrus Yan Darius Vu commented ·

It's really a problem regarding to web development, which I am not very familiar with, you should ask professionals about this via other channels, and, hope these threads help, basically you should self-host a web page:

https://stackoverflow.com/questions/22607150/getting-the-url-parameters-inside-the-html-page

https://stackoverflow.com/questions/2129457/how-to-display-url-parameters-in-php-script

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

@Citrus Yan

Thank you so much, I will investigate about it. However, I believe that "Forgot Password" is very important in game/app development. But it is really difficult to implement this task using Playfab. I think that the team should also think about that and soon develop the feature for this - "Forgot Password"

0 Likes 0 ·
Darius Vu avatar image Darius Vu Citrus Yan commented ·

Hi @Citrus Yan

I have the solution to fix this issue as below:

In Azure function, I find the Playfab ID from the contact email. Then I get the Token from Player Internal Data using Playfab ID and run the reset password function.

I tested it by setting manually the password and email. And it is working well.

However, do you know how to execute the Azure function directly from Unity client (don't use automation in Playfab Manager) and pass an email and new password to Azure function as inputs?

//get the Playfab ID from the contact email
var userAccountInfoRequest = new LookupUserAccountInfoRequest
{
	Email = contactEmail,               
};
var userAccountInfoDataResponse = await adminAPI.GetUserAccountInfoAsync(userAccountInfoRequest);
string playfabID = userAccountInfoDataResponse.Result.UserInfo.PlayFabId;

0 Likes 0 ·
Citrus Yan avatar image
Citrus Yan answered

I still think using Azure Function would be the best way to go, may I know have you tried that? And if so, what's the problems you're facing?

2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Darius Vu avatar image Darius Vu commented ·

Hi Citrus Yan,

For using Azure Function, I also tried to do it. But actually, I also don't know exactly about the steps that I have to do and the example code for Azure function to call the the API - Reset Password using the store Token that is saved as the player's internal data and new password. Could you give me the progress steps and the example of Azure function for that?

I am grateful so much for your support!!!

0 Likes 0 ·
Darius Vu avatar image Darius Vu commented ·

Hi Citrus Yan,
I referred this quickstart to make the PlayFab CloudScript - "HelloWorld" using Azure Functions.

https://docs.microsoft.com/en-us/gaming/playfab/features/automation/cloudscript-af/quickstart

Now, I can create a function and publish it in Azure. Then I can register this function in Playfab site and call it in Unity client.

However, now I don't know how to write the "ResetPassword.cs" to use the Token stored in Internal Data and the new password from users to call ResetPassword to do the password resetting. So could you give me the "ResetPassword.cs" example to help me?

Thank you so much.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.