Yesterday I updated Nakama from version 2.11.1 to 2.12.0 and I noticed a problem, I’ll explain it:
In my app (I use Unity as client) when I do the signup with facebook, first Nakama assigns a temporary username to the user, then I acquire the username desired by the user and update it with “client.UpdateAccountAsync()”. If I go to check the user on the nakama dashboard (port 7351), the username is updated correctly on db, but if the user continues to play in that session, he continues to see the temporary username, for example when the leaderboard is retrieved or in the notifications.
I also update the username locally, so I don’t think my problem is on my side. This feature has always been like that and it always worked, it hasn’t worked since I updated Nakama (I haven’t changed my code).
Another strange thing also happens: if the user logs out and logs in, everything settles down. But if the user closes the app and reopens it (I save the token locally and restore it), the token is no longer valid (without having expired). At that point you need to login again, but from that point the problem no longer arises.
It’s as if the token remains tied to the temporary username and the new login is no longer valid because the username is different. Is this a Nakama problem or am I mistaken?
Thank you in advance.
@antoniocapizzi95 This is not a problem with Nakama 2.11.1 and 2.12.0 or similar upgrades.
I think the confusion arises from unfamiliarity with how Nakama caches the username for a player. The session token for the user (a JWT token) contains lots of cached info to optimize out some database operations which would otherwise be costly to perform on each request.
A quick view at the contents of a session token shows:
{
"uid": "ab5b9785-111e-4df5-a637-9868add18db4",
"usn": "FhTraGCTNv",
"exp": 1591472497
}
The "usn"
field in the JSON is the username for the player. When a username is updated in Nakama you can either re-authenticate the user or use a simple RPC function tor replace the player’s session token. A quick example of what this could look like in Go:
func refreshToken(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
userId, ok := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
if !ok {
logger.Warn("no user ID in context")
return "", runtime.NewError("permission denied", 7)
}
account, err := nk.AccountGetId(ctx, userId)
if err != nil {
logger.Error("error retrieving account: %v", err.Error())
return "", runtime.NewError("error retrieving account", 13)
}
// TODO check if the account has been disabled
token, _, err := nk.AuthenticateTokenGenerate(account.User.Id, account.User.Username, nil, 0)
if err != nil {
logger.Error("error generating token: %v", err.Error())
return "", runtime.NewError("error generating token", 13)
}
return token, nil
}
The code is even shorter and easier in Lua of course. Have a look at the function reference for the relevant functions.
https://heroiclabs.com/docs/runtime-code-function-reference/#authenticate