0

As a learning exercise I thought I'd try to access the Xbox services API through the RESTful interface. I don't have much experience with APIs, but using PHP I tried simply sending a POST request as described on this MS users batch profile settings post guide.

$url = "https://profile.xboxlive.com/users/batch/profile/settings";
$data = array(
    "userIds" => ["2533274791381930"],
    "settings" => ["GameDisplayName", "GameDisplayPicRaw", "Gamerscore", "Gamertag"]
);

$options = array(
    'http' => array(
        'header'  => "x-xbl-contract-version: 2\r\n".
                     "Content-Type: application/json\r\n",                   
        'method'  => 'POST',
        'content' => json_encode($data),
    ),
);

$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
echo $result;

Running this gives an error:

Warning: file_get_contents(https://profile.xboxlive.com/users/batch/profile/settings): Failed to open stream: HTTP request failed! HTTP/1.1 401 Unauthorized

This error implies that I need some authorisation, but the guide linked above doesn't say anything about requesting/including tokens/secrets but I thought I'd try anyway...so after configuring an application in the Azure Portal I updatd my code as shown below using the client ID and client secret I created.

$clientId = 'xxxxxxxxxxxxxxxxxxx';
$clientSecret = 'yyyyyyyyyyyyyyyyyyyy';
$grantType = 'client_credentials';
$scope = 'https://graph.microsoft.com/.default';

// Get an access token
$tokenUrl = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
$data = array(
    'client_id' => $clientId,
    'client_secret' => $clientSecret,
    'grant_type' => $grantType,
    'scope' => $scope
);

$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        'method'  => 'POST',
        'content' => http_build_query($data),
    ),
);

$context  = stream_context_create($options);
$result = file_get_contents($tokenUrl, false, $context);
$accessToken = json_decode($result)->access_token;

// Make a request to the API
$url = "https://profile.xboxlive.com/users/batch/profile/settings";
$data = array(
    "userIds" => ["2533274791381930"],
    "settings" => ["GameDisplayName", "GameDisplayPicRaw", "Gamerscore", "Gamertag"]
);

$options = array(
    'http' => array(
        'header'  => "Authorization: Bearer ".$accessToken."\r\n".
                      "x-xbl-contract-version: 2\r\n".
                     "Content-Type: application/json\r\n",
        'method'  => 'POST',
        'content' => json_encode($data),
    ),
);

$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
echo $result;

This gives a different error:

file_get_contents(https://login.microsoftonline.com/common/oauth2/v2.0/token): Failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request

At this point I'm at a total loss and not even sure I'm going down the right path. I don't think there's anything wrong with my code so maybe I'm missing something? I'm trying to do this using PHP and no middleware or third party APIs. I didn't think it would be this hard!

Do I need to be part of the Xbox Live Creators Program to access the API? There's conflicting information online.

Any advice is greatly appreciated.

Dan Twining
  • 640
  • 4
  • 17
  • 30
  • 2
    _"Do I need to be part of the Xbox Live Creators Program to access the API?"_ Aren't you? / _"using PHP and no middleware or third party APIs"_ So, the Xbox services API you mention is not third party, must mean you have it under your control. Why do you ask then if you need to be part of some Xbox program, when you own the API? Questions over questions. [Why can't I ask customer service-related questions?](https://meta.stackoverflow.com/a/255746/367456) – hakre Jul 23 '23 at 22:28
  • 400 responses usually contain information about what was wrong with your request. Follow the advice in [this answer](https://stackoverflow.com/a/15620189/283366) to get the response body for debugging – Phil Jul 23 '23 at 23:07
  • 1
    [_"`/common` cannot be used for the client credentials grant. Per the docs, you'll need to use either the tenant GUID or the tenant's domain-name format."_](https://github.com/MicrosoftDocs/azure-docs/issues/100978#issuecomment-1303995270) – Phil Jul 23 '23 at 23:14
  • The guide you linked to says `Authorization - To access a profile, only a normal auth token and claims are needed.`...so yeah it does mention tokens. I think you need to read the relevant parts of the API's overall documentation to learn how to authenticate a request. – ADyson Jul 24 '23 at 06:43

0 Answers0