Authentication for UWP projects

To take advantage of Xbox Live features in games, a user needs to create an Xbox Live profile to identify themselves in the Xbox Live community.

Xbox Live services keep track of game-related activities using that Xbox Live profile, such as:

  • The user's gamertag and gamer picture
  • Who the user's gaming friends are
  • What games the user has played
  • What achievements the user has unlocked
  • Where the user stands on the leaderboard for a particular game

When a user wants to access Xbox Live services in a particular game on a particular device, the user needs to authenticate first. The game can call Xbox Live APIs to initiate the authenticate process.

In some cases, the user will be presented with an interface to provide additional information, such as entering the username and password of the Microsoft Account to use, giving permission consent to the game, resolving account issues, accepting new terms of use, etc.

Once authenticated, the user is associated with that device until they explicitly sign out of Xbox Live from the Xbox app. Only one player is allowed to be authenticated on a non-console device at a time (for all Xbox Live games); for a new player to be authenticated on a non-console device, the existing authenticated player must sign out first.

Steps to Sign-In

At a high level, you use the Xbox Live APIs by following these steps:

  1. Create an XboxLiveUser object to represent the user.
  2. Sign-in silently to Xbox Live at startup.
  3. Attempt to sign-in with UX if required.
  4. Create an Xbox Live context based on the interacting user.
  5. Use the Xbox Live context to access Xbox Live services.
  6. When the game exits or the user signs-out, release the XboxLiveUser object and XboxLiveContext object by setting them to null.

Creating an XboxLiveUser object

Most of the Xbox Live activities are related to the Xbox Live User. As a game developer, you need to first create an XboxLiveUser object to represent the local user.

C++:

auto xboxUser = std::make_shared<xbox_live_user>(Windows::System::User^ windowsSystemUser);

C++/CX (WinRT):

XboxLiveUser xboxUser = ref new XboxLiveUser(Windows::System::User^ windowsSystemUser);

C# (WinRT):

XboxLiveUser xboxUser = new XboxLiveUser(Windows.System.User windowsSystemUser);

Sign-in silently to Xbox Live at startup

Your game should start to authenticate the user to Xbox Live as early as possible after launching, even before you present the user interface, to pre-fetch data from Xbox Live services.

To authenticate the local user silently, call:

C++:

pplx::task<xbox_live_result<sign_in_result>> xbox_live_user::signin_silently(Platform::Object^ coreDispatcher)

C++/CX (WinRT):

Windows::Foundation::IAsyncOperation<SignInResult^>^ XboxLiveUser::SignInSilentlyAsync(Platform::Object^ coreDispatcher)

C# (WinRT):

Microsoft.Xbox.Services.System.SignInResult XboxLiveUser.SignInSilentlyAsync(Windows.UI.Core.CoreDispatcher coreDispatcher);
  • coreDispatcher

    Thread Dispatcher is used to communicate between threads. Although the silent sign-in API is not going to show any UI, XSAPI still needs the UI thread dispatcher for getting the information about your app's locale.

    You can get the static UI thread dispatcher by calling Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher in the UI thread. Or, if you're certain that this API is being called on the UI thread, you can pass in nullptr (for example on JS UWA).

There are 3 possible outcomes from the silent sign-in attempt:

Success

If the device is online, this outcome means the user authenticated to Xbox Live successfully, and we were able to get a valid token.

If the device is offline, this outcome means the user has previously authenticated to Xbox Live successfully, and has not explicitly signed-out from this title. Note in this case there is no guarantee that title has access to a valid token, it is only guaranteed that the user's identity is known and has been verified. The identity of the user is known to the title via their xbox user ID (xuid) and gamertag.

UserInteractionRequired

This outcome means the runtime was unable to sign-in the user silently. The game should call xbox_live_user::sign_in which invokes the Xbox Identity Provider to show the necessary UX flow for the user to sign-up/sign-in.

Common issues are:

  • User does not have a Microsoft Account.
  • User has not set a preferred Microsoft Account for gaming.
  • The selected Microsoft Account doesn't have an Xbox Live profile.
  • User needs to accept Microsoft Account consent.

Other errors

This outcome means the runtime was unable to sign-in due to other reasons. Typically these issues are not actionable by the game or the user. When using the C++ API, you would need to check error by checking xbox_live_result<>.err(); on WinRT, you would need to catch Platform::Exception^.

Attempt to sign-in with UX if required

Your game should authenticate the user to Xbox Live with UX enabled when silent sign-in was unsuccessful, and you are ready to present the user interface.

To authenticate the local user with UX, call

C++:

pplx::task<xbox_live_result<sign_in_result>> xbox_live_user::signin(Platform::Object^ coreDispatcher)

C++/CX (WinRT):

Windows::Foundation::IAsyncOperation<SignInResult^>^ XboxLiveUser::SignInAsync(Platform::Object^ coreDispatcher)

C# (WinRT):

Microsoft.Xbox.Services.System.SignInResult  XboxLiveUser.SignInAsync(Windows.UI.Core.CoreDispatcher coreDispatcher);
  • coreDispatcher

    Thread Dispatcher is used to communication between threads. Sign in API requires the UI dispatcher so that it can show the sign in UI and get the information about your appx's locale. You can get the static UI thread dispatcher by calling Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher in the UI thread. Or if you're certain that this API is being called on the UI thread, you can pass in nullptr (for example on JS UWA).

There are 3 possible outcomes from the sign-in attempt with UX:

Success

If the device is online, this sign-in outcome means the user authenticated to Xbox Live successfully, and we were able to get a valid token.

If the device is offline, this sign-in outcome means the user has previously authenticated to Xbox Live successfully, and has not explicitly signed-out from this title. Note in this case there is no guarantee that title has access to a valid token, it is only guaranteed that the user's identity is known and has been verified. The identity of the user is known to the title xbox user ID (xuid) and gamertag.

UserCancel

This sign-in outcome means that the user cancelled the sign-in operation before completion.

When this outcome happens, the game should NOT automatically retry sign-in with UX. Instead, it should present in-game UX that allows the user to retry the sign-in operation. For example, a sign-in button.

Other errors

This sign-in outcome means the runtime was unable to sign-in due to other reasons.

Typically these issues are not actionable by the game or the user. When using C++ API, you would need to check the error by checking xbox_live_result<>.err(); on WinRT, you would need to catch Platform::Exception^.

Sign-In Code Examples

C++


#include "xsapi\services.h" // contains the xbox::services::system namespace

using namespace xbox::services::system; // contains definitions necessary for sign-in

void SignInSample::SignIn()
{
    //1. Create an xbox_live_user object
    m_user = std::make_shared<xbox::services::system::xbox_live_user>(); // m_user declared in header file

    //2. Sign-In silently to Xbox Live at startup
    m_user->signin_silently()
        .then([this](xbox::services::xbox_live_result<xbox::services::system::sign_in_result> result)
    {
        if (!result.err())
        {
            auto rPayload = result.payload();
            switch (rPayload.status())
            {
            case xbox::services::system::sign_in_status::success:
                // sign-in successful
                signIn = true;
                break;
            case xbox::services::system::sign_in_status::user_interaction_required:
                // 3. Attempt to sign-in with UX if required
                m_user->signin(Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher)
                    .then([this](xbox::services::xbox_live_result<xbox::services::system::sign_in_result> loudResult) // use task_continuation_context::use_current() to make the continuation task running in current apartment 
                {
                    if (!loudResult.err())
                    {
                        auto resPayload = loudResult.payload();
                        switch (resPayload.status())
                        {
                        case xbox::services::system::sign_in_status::success:
                            // sign-in successful
                            signIn = true;
                            break;
                        case xbox::services::system::sign_in_status::user_cancel:
                            // user cancelled sign in 
                            // present in-game UX that allows the user to retry the sign-in operation. (For example, a sign-in button)
                            break;
                        }
                    }
                    else
                    {
                        //login has failed at this point
                    }
                }, concurrency::task_continuation_context::use_current());
                break;
            }
        }
    });
    if (signIn)
    {
        // 4. Create an Xbox Live context based on the interacting user
        m_xboxLiveContext = std::make_shared<xbox::services::xbox_live_context>(m_user); // m_xboxLiveContext declared in header file

        // add sign out event handler
        AddSignOut();
    }
}

void SignInSample::AddSignOut()
{
    xbox::services::system::xbox_live_user::add_sign_out_completed_handler(
        [this](const xbox::services::system::sign_out_completed_event_args&)

    {
        // 6. When the game exits or the user signs-out, release the XboxLiveUser object and XboxLiveContext object by setting them to null
        m_user = NULL;
        m_xboxLiveContext = NULL;
    });
}

C# (WinRT)


using System.Diagnostics;
using Microsoft.Xbox.Services.System;
using Microsoft.Xbox.Services;

public async Task SignIn()
{
    bool signedIn = false;

    // Get a list of the active Windows users.
    IReadOnlyList<Windows.System.User> users = await Windows.System.User.FindAllAsync();

    // Acquire the CoreDispatcher which will be required for SignInSilentlyAsync and SignInAsync.
    Windows.UI.Core.CoreDispatcher UIDispatcher = Windows.UI.Xaml.Window.Current.CoreWindow.Dispatcher; 

    try
    {
        // 1. Create an XboxLiveUser object to represent the user
        XboxLiveUser primaryUser = new XboxLiveUser(users[0]);

        // 2. Sign-in silently to Xbox Live
        SignInResult signInSilentResult = await primaryUser.SignInSilentlyAsync(UIDispatcher);
        switch (signInSilentResult.Status)
        {
            case SignInStatus.Success:
                signedIn = true;
                break;
            case SignInStatus.UserInteractionRequired:
                //3. Attempt to sign-in with UX if required
                SignInResult signInLoud = await primaryUser.SignInAsync(UIDispatcher);
                switch(signInLoud.Status)
                {
                    case SignInStatus.Success:
                        signedIn = true;
                        break;
                    case SignInStatus.UserCancel:
                        // present in-game UX that allows the user to retry the sign-in operation. (For example, a sign-in button)
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
        if(signedIn)
        {
            // 4. Create an Xbox Live context based on the interacting user
            Microsoft.Xbox.Services.XboxLiveContext m_xboxLiveContext = new Microsoft.Xbox.Services.XboxLiveContext(user);

            //add the sign out event handler
            XboxLiveUser.SignOutCompleted += OnSignOut;
        }
    }
    catch (Exception e)
    {
        Debug.WriteLine(e.Message);
    }

}

public void OnSignOut(object sender, SignOutCompletedEventArgs e)
    {
        // 6. When the game exits or the user signs-out, release the XboxLiveUser object and XboxLiveContext object by setting them to null
        primaryUser = null;
        xboxLiveContext = null;
    }

Sign Out

Handling user sign-out completed event

The user will sign-out from a title if one of the following happens:

  • The user signed-out from the Xbox App (Windows 10) or console shell (Xbox One or later). Signing out will affect all Xbox Live enabled apps installed for this user.
  • The user switched to a different Microsoft Account.
  • The user signed into the same title from a different device.

In all these cases, the title will receive an event from the xbox_live_user::add_sign_out_completed_handler or XboxLiveUser::SignOutCompleted handlers. The game must handle the "sign-out completed" event appropriately:

  • The game should display clear visual indication to the user that the user has signed-out from Xbox Live.
  • The game cannot call any Xbox Live service APIs in the event handler, because the user has already signed-out and there is no authorization token available.

Sign Out Handler Code Samples

C++

xbox::services::system::xbox_live_user::add_sign_out_completed_handler(
        [this](const xbox::services::system::sign_out_completed_event_args&)

    {
        // 6. When the game exits or the user signs-out, release the XboxLiveUser object and XboxLiveContext object by setting them to null
        m_user = NULL;
        m_xboxLiveContext = NULL;
    });

C# (WinRT)

XboxLiveUser.SignOutCompleted += OnUserSignOut;

public void OnSignOut(object sender, SignOutCompletedEventArgs e)
        {
            // 6. When the game exits or the user signs-out, release the XboxLiveUser object and XboxLiveContext object by setting them to null
            primaryUser = null;
            xboxLiveContext = null;
        }

Determining if the device is offline

If no user has been signed-in before, offline sign-in will not be achievable.

If the title can be played offline (Campaign mode, etc.):

  • The title can allow the user to play and record game progress via the WriteInGameEvent API and the Connected Storage API; both of them work properly while the device is offline.

If the title cannot be played offline (Multiplayer game or Server-based game, etc.):

  • The title should call GetNetworkConnectivityLevel to find out if the device is offline, and inform the user about the status and possible solutions (for example, "You need to connect to Internet to continue...").

Online Status Code Samples

C++


using namespace Windows::Networking::Connectivity;

//Retrieve the ConnectionProfile
ConnectionProfile^ InternetConnectionProfile = NetworkInformation::GetInternetConnectionProfile();

NetworkConnectivityLevel connectionLevel = InternetConnectionProfile->GetNetworkConnectivityLevel();

switch (connectionLevel)
{
case NetworkConnectivityLevel::InternetAccess:
    // User is connected to the internet.
    break;
case NetworkConnectivityLevel::ConstrainedInternetAccess: //Limited Internet Access Possible Authentication Required
     // display error message for user.
    LogConnectivityLine("Game Offline: Limited internet access, browser authentication may be required. "); //function writes to UI
    break;
default:
    LogConnectivityLine("Game Offline: No internet access.");
    break;
}

C# (WinRT)

using Windows.Networking.Connectivity;

//Retrieve the ConnectionProfile
string connectionProfileInfo = string.Empty;
ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();

NetworkConnectivityLevel connectionLevel = InternetConnectionProfile.GetNetworkConnectivityLevel();

switch(connectionLevel)
    {
        case NetworkConnectivityLevel.InternetAccess:
            // User is connected to the internet.
            break;
        case NetworkConnectivityLevel.ConstrainedInternetAccess: //Limited Internet Access Possible Authentication Required
            // display error message for user.
            LogConnectivityLine("Game Offline: Limited internet access, browser authentication may be required. "); //function writes to UI
            break;
        default:
            LogConnectivityLine("Game Offline: No internet access.");
            break;
    }