The server has built-in authentication so clients can only send requests and connect if they have the server key. The default server key is defaultkey but it is very important to set a unique value. This value should be embedded within client code.
When authentication is successful a client can create a session as a user.
Every user account is created from one of the options used to authenticate. We call each of these options a “link” because it’s a way to access the user’s account. You can add more than one link to each account which is useful to enable users to login in multiple ways across different devices.
Before you interact with the server, you must obtain a session token by authenticating with the system. The authentication system is very flexible. You could register a user with an email address, link their Facebook account, and use it to login from another device.
By default the system will create a user automatically if the identifier used to authenticate did not previously exist in the system. This pattern is shown in the device section.
For full examples on the best way to handle registering and login in each of the clients have a look at their guides.
A device identifier can be used as a way to unobtrusively register a user with the server. This offers a frictionless user experience but can be unreliable because device identifiers can sometimes change in device updates.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
A device identifier must contain alphanumeric characters with dashes and be between 10 and 128 bytes.
// This import is only required with React Native
vardeviceInfo=require('react-native-device-info');vardeviceId=null;try{constvalue=awaitAsyncStorage.getItem('@MyApp:deviceKey');if(value!==null){deviceId=value}else{deviceId=deviceInfo.getUniqueID();AsyncStorage.setItem('@MyApp:deviceKey',deviceId).catch(function(error){console.log("An error occurred: %o",error);});}}catch(error){console.log("An error occurred: %o",error);}varcreate=true;constsession=awaitclient.authenticateDevice(deviceId,create,"mycustomusername");console.info("Successfully authenticated:",session);
Client
1
2
3
4
// Should use a platform API to obtain a device identifier.vardeviceId=System.Guid.NewGuid().ToString();varsession=awaitclient.AuthenticateDeviceAsync(deviceId);System.Console.WriteLine("New user: {0}, {1}",session.Created,session);
# Unique ID is not supported by Godot in HTML5, use a different way to generate an id, or a different authentication option.vardeviceid=OS.get_unique_id()varsession:NakamaSession=yield(client.authenticate_device_async(deviceid),"completed")ifsession.is_exception():print("An error occurred: %s"%session)returnprint("Successfully authenticated: %s"%session)
Client
1
2
3
4
5
6
7
8
9
# Unique ID is not supported by Godot in HTML5, use a different way to generate an id, or a different authentication option.vardeviceid=OS.get_unique_id()varsession:NakamaSession=awaitclient.authenticate_device_async(deviceid)ifsession.is_exception():print("An error occurred: %s"%session)returnprint("Successfully authenticated: %s"%session)
Client
1
2
3
4
5
6
7
8
9
10
-- login using the token and create an account if the user-- doesn't already existlocalresult=client.authenticate_device(defold,uuid(),nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")end-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)
// You can obtain device id for multiplatforms using a package like `device_info_plus`
finalsession=awaitclient.authenticateDevice(deviceId:'<obtained_device_id>');
In games it is often a better option to use Google or Game Center to unobtrusively register the user.
Users can be registered with an email and password. The password is hashed before it’s stored in the database server and cannot be read or “recovered” by administrators. This protects a user’s privacy.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
An email address must be valid as defined by RFC-5322 and passwords must be at least 8 characters.
autosuccessCallback=[](NSessionPtrsession){std::cout<<"Authenticated successfully. User ID: "<<session->getUserId()<<std::endl;};autoerrorCallback=[](constNError&error){};stringemail="email@example.com";stringpassword="3bc8f72e95a9";stringusername="mycustomusername";boolcreate=true;client->authenticateEmail(email,password,username,create,{},successCallback,errorCallback);
localresult=client.authenticate_email("email@example.com","3bc8f72e95a9",nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")end-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)
Nakama supports console authentication for all major platforms, including Nintendo Switch, Xbox One and Series X|S, and PlayStation 4/5.
Requesting Access
Console authentication is only available to developers verified by the respective console platform providers (Sony, Microsoft, Nintendo). To request access, please contact us.
The console authentication flow is similar to the device authentication flow, but requires a console identifier and a console user identifier.
Note that the examples below are only meant to be illustrative. Complete documentation can only be provided following your verification by the console platform provider(s).
Client
1
2
3
4
5
6
7
8
// Xbox authenticationvarsession=awaitclient.AuthenticateCustomAsync("xbox|<xbox_code>");// PlayStation authenticationvarsession=awaitclient.AuthenticateCustomAsync("psn|<<psn_code>>");// Nintendo authenticationvarsession=awaitclient.AuthenticateCustomAsync("nintendo|<<nintendo_code>>");
Client
1
2
3
4
5
6
7
8
// Xbox authentication
client->authenticateCustom("xbox|<xbox_code>",{},successCallback,errorCallback);// PlayStation authentication
client->authenticateCustom("psn|<<psn_code>>",{},successCallback,errorCallback);// Nintendo authentication
client->authenticateCustom("nintendo|<<nintendo_code>>",{},successCallback,errorCallback);
Code snippet for this language Defold has not been found. Please choose another language to show equivalent examples.
Code snippet for this language cURL has not been found. Please choose another language to show equivalent examples.
Code snippet for this language REST has not been found. Please choose another language to show equivalent examples.
Code snippet for this language JavaScript/Cocos2d-js has not been found. Please choose another language to show equivalent examples.
Code snippet for this language Java/Android has not been found. Please choose another language to show equivalent examples.
Code snippet for this language Godot 3 has not been found. Please choose another language to show equivalent examples.
Code snippet for this language Godot 4 has not been found. Please choose another language to show equivalent examples.
The server supports a lot of different social services with register and login. With each provider the user account will be fetched from the social service and used to setup the user. In some cases a user’s friends will also be fetched and added to their friends list.
To register or login as a user with any of the providers an OAuth or access token must be obtained from that social service.
Follow the Apple Developer documentation for integrating Sign in with Apple in your applications.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
autosuccessCallback=[](NSessionPtrsession){std::cout<<"Authenticated successfully. User ID: "<<session->getUserId()<<std::endl;};autoerrorCallback=[](constNError&error){};std::stringusername="...";std::stringtoken="...";client->authenticateApple(token,username);
-- Use https://defold.com/assets/siwa/localtoken="..."localusername="..."localresult=client.authenticate_apple(token,username)ifnotresult.tokenthenprint("Unable to login")end-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)
With Facebook you’ll need to add the Facebook SDK to your project which can be downloaded online. Follow their guides on how to integrate the code. With a mobile project you’ll also need to complete instructions on how to configure iOS and Android.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
When authenticating via Facebook, the following profile fields are fetched and stored in the user account:
ID
Name
Email
Photo
Additionally, you can optionally import Facebook friends into Nakama’s friend graph when authenticating. To do this, set import to true.
Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/facebook?create=true&username=mycustomusername&import=true"\
--user 'defaultkey:'\
--data '{"token":"valid-oauth-token"}'# Supports the use of both OAuth and Facebook Limited Login (JWT) tokens.
autologinFailedCallback=[](constNError&error){};autologinSucceededCallback=[](NSessionPtrsession){cout<<"Authenticated successfully. User ID: "<<session->getUserId()<<endl;};std::stringoauthToken="...";boolimportFriends=true;client->authenticateFacebook(oauthToken,"mycustomusername",true,importFriends,{},loginSucceededCallback,loginFailedCallback);
-- Use the official Defold Facebook integration (www.defold.com/extension-facebook)localpermissions={"public_profile"}-- login using read permissions-- there is no need to specify a publishing audience when requesting read permissionsfacebook.login_with_permissions(permissions,facebook.AUDIENCE_NONE,function(self,data)localresult=client.authenticate_facebook(facebook.access_token(),nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")returnend-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)end)
Ensure that you’ve configured your FB Instant App secret for Nakama and initialized the Facebook Instant Games SDK using FBInstant.initializeAsync().
Code snippet for this language .NET/Unity has not been found. Please choose another language to show equivalent examples.
Code snippet for this language C++/Unreal/Cocos2d-x has not been found. Please choose another language to show equivalent examples.
Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/facebookinstantgame?create=true&username=mycustomusername"\
--user 'defaultkey:'\
--data '{"token":"valid-oauth-token"}'# Supports the use of both OAuth and Facebook Limited Login (JWT) tokens.
-- Use the official Defold Facebook Instant Games integration (www.defold.com/extension-fbinstant)fbinstant.get_signed_player_info("developer payload",function(self,signature)localresult=client.authenticate_facebook_instant_game(signature,nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")returnend-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)end)
Similar to Facebook, for registration and login you should use one of Google’s client SDKs.
Google Play Games Plugin >=v0.11.x
For Google Play Games Plugin v0.11.x or greater, you must use Server-Side Access to Google Play Games Services. To enable this behavior in Nakama you must obtain credentials that include scopes to access Players:get endpoint.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
autosuccessCallback=[](NSessionPtrsession){std::cout<<"Authenticated successfully. User ID: "<<session->getUserId()<<std::endl;};autoerrorCallback=[](constNError&error){};stringoauthToken="...";client->authenticateGoogle(oauthToken,"mycustomusername",true,{},successCallback,errorCallback);
localresult=client.authenticate_google(oauth_token,nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")end-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)
Apple devices have built-in authentication which can be done without user interaction through Game Center. The register or login process is a little complicated because of how Apple’s services work.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
autosuccessCallback=[](NSessionPtrsession){std::cout<<"Authenticated successfully. User ID: "<<session->getUserId()<<std::endl;};autoerrorCallback=[](constNError&error){};std::stringplayerId="...";std::stringbundleId="...";NTimestamptimestampSeconds="...";std::stringsalt="...";std::stringsignature="...";std::stringpublicKeyUrl="...";client->authenticateGameCenter(playerId,bundleId,timestampSeconds,salt,signature,publicKeyUrl,"mycustomusername",true,{},successCallback,errorCallback);
-- Use https://defold.com/assets/gamekit/localbundle_id="..."localplayer_id="..."localpublic_key_url="..."localsalt="..."localsignature="..."localtimestamp_seconds=0localresult=client.authenticate_game_center(bundle_id,player_id,public_key_url,salt,signature,timestamp_seconds,nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")end-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)
Steam requires you to configure the server before you can register a user. Have a look at the configuration section for what settings you need for the server.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
You can optionally import Steam friends into Nakama’s friend graph when authenticating. To do this, set import to true.
autosuccessCallback=[](NSessionPtrsession){std::cout<<"Authenticated successfully. User ID: "<<session->getUserId()<<std::endl;};autoerrorCallback=[](constNError&error){};stringtoken="...";stringusername="mycustomusername";boolcreate=true;boolimportFriends=true;client->authenticateSteam(token,username,create,importFriends,{},successCallback,errorCallback);
-- Use https://defold.com/assets/steamworks/localresult=client.authenticate_steam(steam_token,nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")end-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)
A custom identifier can be used in a similar way to a device identifier to login or register a user. This option should be used if you have an external or custom user identity service which you want to use. For example EA’s Origin service handles accounts which have their own user IDs.
A custom identifier must contain alphanumeric characters with dashes and be between 6 and 128 bytes.
You can choose a custom username when creating the account. To do this, set username to a custom name. If you want to only authenticate without implicitly creating a user account, set create to false.
autosuccessCallback=[](NSessionPtrsession){std::cout<<"Authenticated successfully. User ID: "<<session->getUserId()<<std::endl;};autoerrorCallback=[](constNError&error){};stringid="some-custom-id";stringusername="mycustomusername";boolcreate=true;client->authenticateCustom(id,username,create,{},successCallback,errorCallback);
localresult=client.authenticate_custom(custom_id,nil,true,"mycustomusername")ifnotresult.tokenthenprint("Unable to login")end-- store the token and use it when communicating with the serverclient.set_bearer_token(result.token)
intport=7350;// different port to the main API port
boolcreateStatus=true;// if the server should show the user as online to others.
// define real-time client in your class as NRtClientPtr rtClient;
rtClient=client->createRtClient(port);// define listener in your class as NRtDefaultClientListener listener;
listener.setConnectCallback([](){cout<<"Socket connected."<<endl;});rtClient->setListener(&listener);rtClient->connect(session,createStatus);
# Make this a node variable, or it will disconnect when the function that creates it returns.onreadyvarsocket:=Nakama.create_socket_from(client)func_ready():varconnected:NakamaAsyncResult=yield(socket.connect_async(session),"completed")ifconnected.is_exception():print("An error occurred: %s"%connected)returnprint("Socket connected.")
Client
1
2
3
4
5
6
7
8
9
10
11
# Make this a node variable, or it will disconnect when the function that creates it returns.@onreadyvarsocket:=Nakama.create_socket_from(client)func_ready():varconnected:NakamaAsyncResult=awaitsocket.connect_async(session)ifconnected.is_exception():print("An error occurred: %s"%connected)returnprint("Socket connected.")
Client
1
2
3
4
5
6
localsocket=client.create_socket()localok,err=socket.connect()ifnotokthenprint("Unable to connect: ",err)end
You can link one or more other login option to the current user. This makes it easy to support multiple logins with each user and easily identify a user across devices.
You can only link device Ids, custom Ids, and social provider IDs which are not already in-use with another user account.
constcustomId="some-custom-id";constsuccess=awaitclient.linkCustom(session,customId);console.log("Successfully linked custom ID to current user.");
Client
1
2
3
conststringcustomId="some-custom-id";awaitclient.LinkCustomAsync(session,customId);System.Console.WriteLine("Id '{0}' linked for user '{1}'",customId,session.UserId);
StringcustomId="some-custom-id";client.linkCustom(session,customId).get();System.out.format("Id %s linked for user %s",customId,session.getUserId());
Client
1
2
3
4
5
6
7
8
varcustom_id="some-custom-id"varlinked:NakamaAsyncResult=yield(client.link_custom_async(session,custom_id),"completed")iflinked.is_exception():print("An error occurred: %s"%linked)returnprint("Id '%s' linked for user '%s'"%[custom_id,session.user_id])
Client
1
2
3
4
5
6
7
8
varcustom_id="some-custom-id"varlinked:NakamaAsyncResult=awaitclient.link_custom_async(session,custom_id)iflinked.is_exception():print("An error occurred: %s"%linked)returnprint("Id '%s' linked for user '%s'"%[custom_id,session.user_id])
constcustomId="some-custom-id";constsuccess=awaitclient.unlinkCustom(session,customId);console.info("Successfully unlinked custom ID from the current user.");
Client
1
2
3
conststringcustomId="some-custom-id";awaitclient.UnlinkCustomAsync(session,customId);System.Console.WriteLine("Id '{0}' unlinked for user '{1}'",customId,session.UserId);
Client
1
2
3
4
5
6
7
8
9
10
11
12
autounlinkFailedCallback=[](constNError&error){};autounlinkSucceededCallback=[](){cout<<"Successfully unlinked custom ID from the current user."<<endl;};std::stringcustomid="some-custom-id";client->unlinkCustom(customid,unlinkSucceededCallback,unlinkFailedCallback);
Client
1
2
3
StringcustomId="some-custom-id";client.unlinkCustom(session,customId).get();System.out.format("Id %s unlinked for user %s",customId,session.getUserId());
Client
1
2
3
4
5
6
7
8
varcustom_id="some-custom-id"varunlinked:NakamaAsyncResult=yield(client.unlink_custom_async(session,custom_id),"completed")ifunlinked.is_exception():print("An error occurred: %s"%unlinked)returnprint("Id '%s' unlinked for user '%s'"%[custom_id,session.user_id])
Client
1
2
3
4
5
6
7
8
varcustom_id="some-custom-id"varunlinked:NakamaAsyncResult=awaitclient.unlink_custom_async(session,custom_id)ifunlinked.is_exception():print("An error occurred: %s"%unlinked)returnprint("Id '%s' unlinked for user '%s'"%[custom_id,session.user_id])
letcustomId="<customId>"letsuccess=tryawaitclient.unlinkCustom(session:session,id:customId)print("Successfully unlinked custom ID from the current user.")