Skip to content
This repository was archived by the owner on Jul 16, 2020. It is now read-only.

Commit 8b21b58

Browse files
committed
sample: Update Xbox sample with XToken auth.
1 parent 0876982 commit 8b21b58

File tree

1 file changed

+74
-40
lines changed

1 file changed

+74
-40
lines changed

samples/InteractiveXboxSample/Game.cpp

Lines changed: 74 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
#include "pch.h"
66
#include "Game.h"
77

8+
#include <ppltasks.h>
9+
810
using namespace DirectX;
911
using namespace Windows::Xbox::Input;
1012
using namespace Windows::Foundation::Collections;
13+
using namespace concurrency;
14+
using namespace Windows::Xbox::System;
1115

1216
using Microsoft::WRL::ComPtr;
1317

@@ -33,50 +37,80 @@ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
3337
#define INTERACTIVE_ID "135704"
3438
#define SHARE_CODE "xe7dpqd5"
3539

36-
// Display a short code to the user in order to obtain a reusable token for future connections.
37-
int authorize(std::string& authorization)
40+
int GetXToken(std::string& token)
3841
{
39-
int err = 0;
40-
char shortCode[7];
41-
size_t shortCodeLength = sizeof(shortCode);
42-
char shortCodeHandle[1024];
43-
size_t shortCodeHandleLength = sizeof(shortCodeHandle);
44-
err = interactive_auth_get_short_code(CLIENT_ID, nullptr, shortCode, &shortCodeLength, shortCodeHandle, &shortCodeHandleLength);
45-
if (err) return err;
46-
47-
std::cout << "Visit " << "https://www.mixer.com/go?code=" << shortCode;
48-
49-
// Wait for OAuth token response.
50-
char refreshTokenBuffer[1024];
51-
size_t refreshTokenLength = sizeof(refreshTokenBuffer);
52-
err = interactive_auth_wait_short_code(CLIENT_ID, nullptr, shortCodeHandle, refreshTokenBuffer, &refreshTokenLength);
53-
if (err)
42+
std::wstring mixerRelyingParty = L"https://mixer.com";
43+
std::wstring authRequestHeaders = L"";
44+
auto platformHttp = ref new Platform::String(L"POST");
45+
auto platformUrl = ref new Platform::String(mixerRelyingParty.c_str());
46+
auto platformHeaders = ref new Platform::String(authRequestHeaders.c_str());
47+
48+
std::wstring wstrReturnedToken = L"";
49+
50+
HRESULT hr = S_OK;
51+
52+
// Note: This would fail certification. You must pop TCUI and allow a user to be chosen.
53+
Windows::Xbox::System::User^ currentUser = Windows::Xbox::System::User::Users->GetAt(0);
54+
if (nullptr == currentUser)
5455
{
55-
if (MIXER_ERROR_TIMED_OUT == err)
56+
OutputDebugStringA("No user signed in. Please sign in a user and try this sample again.");
57+
return E_ABORT;
58+
}
59+
60+
try
61+
{
62+
// Make platform call to get token.
63+
auto asyncOp = currentUser->GetTokenAndSignatureAsync(platformHttp, platformUrl, platformHeaders);
64+
65+
// Construct an object that waits for the AsyncOperation to finish
66+
task<GetTokenAndSignatureResult^> asyncTask = create_task(asyncOp);
67+
68+
// Capture the async then so we can ensure the lambda finishes before continuing
69+
auto asyncFinalise = asyncTask.then(
70+
[&wstrReturnedToken, &hr](
71+
task<GetTokenAndSignatureResult^> operation)
5672
{
57-
std::cout << "Authorization timed out, user did not approve access within the time limit.";
58-
}
59-
else if (MIXER_ERROR_AUTH_DENIED == err)
73+
try
74+
{
75+
GetTokenAndSignatureResult^ result = operation.get();
76+
77+
if (result->Token->IsEmpty())
78+
{
79+
hr = E_UNEXPECTED;
80+
return;
81+
}
82+
83+
wstrReturnedToken = result->Token->Data();
84+
hr = S_OK;
85+
}
86+
catch (Platform::Exception ^ e)
87+
{
88+
hr = e->HResult;
89+
}
90+
});
91+
92+
// Clean up the async task
93+
asyncTask.wait();
94+
asyncOp->Close();
95+
96+
// Wait for the lambda to finish.
97+
asyncFinalise.wait();
98+
99+
// Check for any failures
100+
if (FAILED(hr))
60101
{
61-
std::cout << "User denied access.";
102+
return hr;
62103
}
63104

64-
return err;
105+
// Convert data to utf8
106+
token = converter.to_bytes(wstrReturnedToken);
107+
}
108+
catch (Platform::Exception^ e)
109+
{
110+
return e->HResult;
65111
}
66112

67-
/*
68-
* TODO: This is where you would serialize the refresh token for future use in a way that is associated with the current user.
69-
* Future calls would then only need to check if the token is stale, refresh it if so, and then parse the new authorization header.
70-
*/
71-
72-
// Extract the authorization header from the refresh token.
73-
char authBuffer[1024];
74-
size_t authBufferLength = sizeof(authBuffer);
75-
err = interactive_auth_parse_refresh_token(refreshTokenBuffer, authBuffer, &authBufferLength);
76-
if (err) return err;
77-
78-
authorization = std::string(authBuffer, authBufferLength);
79-
return 0;
113+
return S_OK;
80114
}
81115

82116

@@ -100,7 +134,7 @@ void Game::Initialize(IUnknown* window)
100134

101135
// Get an authorization token for the user to pass to the connect function.
102136
std::string authorization;
103-
err = authorize(authorization);
137+
err = GetXToken(authorization);
104138
if (err)
105139
{
106140
throw err;
@@ -140,15 +174,15 @@ void Game::Initialize(IUnknown* window)
140174
Game* game = (Game*)context;
141175
if (errorCode)
142176
{
143-
std::cerr << errorMessage << "(" << std::to_string(errorCode) << ")" << std::endl;
177+
OutputDebugStringA((std::string("ERROR: ") + errorMessage + "(" + std::to_string(errorCode) + ")").c_str());
144178
}
145179
else
146180
{
147181
// Transaction was captured, now execute the most super awesome interactive functionality!
148182
std::string controlId = game->m_controlsById[transactionId];
149183
if (0 == strcmp("GiveHealth", controlId.c_str()))
150184
{
151-
std::cout << "Giving health to the player!" << std::endl;
185+
OutputDebugStringA("Giving health to the player!\n");
152186
}
153187
}
154188

@@ -199,7 +233,7 @@ void Game::Update(DX::StepTimer const& timer)
199233
int err = interactive_run(m_interactiveSession, 1);
200234
if (err)
201235
{
202-
std::cerr << "Failed to process interactive event, error: " << std::to_string(err);
236+
OutputDebugStringA((std::string("ERROR: Failed to process interactive event: ") + std::to_string(err)).c_str());
203237
}
204238

205239
PIXEndEvent();

0 commit comments

Comments
 (0)