psn-php: Getting 400 after login with Npsso: Client does not have grant type sso_cookie

$psn_client = new Client(); $psn_client->loginWithNpsso('MY TOKEN');

{"error":"unauthorized_client","error_description":"Client does not have grant type: [\"sso_cookie\"]","docs":"https://auth.api.sonyentertainmentnetwork.com/docs/","error_code":4151}

Client error: POST https://auth.api.sonyentertainmentnetwork.com/2.0/oauth/token` resulted in a 400 Bad Request response: {“error”:“unauthorized_client”,“error_description”:“Client does not have grant type: ["sso_cookie"]”,“docs”:"https://a (truncated…)`

Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: POST https://auth.api.sonyentertainmentnetwork.com/2.0/oauth/token` resulted in a 400 Bad Request response: {“error”:“unauthorized_client”,“error_description”:“Client does not have grant type: ["sso_cookie"]”,“docs”:"https://a (truncated…) in C:\xampp\htdocs\psn\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:113 Stack trace: #0 C:\xampp\htdocs\psn\vendor\guzzlehttp\guzzle\src\Middleware.php(65): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response)) #1 C:\xampp\htdocs\psn\vendor\guzzlehttp\promises\src\FulfilledPromise.php(41): GuzzleHttp\Middleware::GuzzleHttp{closure}(Object(GuzzleHttp\Psr7\Response)) #2 C:\xampp\htdocs\psn\vendor\guzzlehttp\promises\src\TaskQueue.php(48): GuzzleHttp\Promise\FulfilledPromise::GuzzleHttp\Promise{closure}() #3 C:\xampp\htdocs\psn\vendor\guzzlehttp\promises\src\Promise.php(248): GuzzleHttp\Promise\TaskQueue->run(true) #4 C:\xampp\htdocs\ in C:\xampp\htdocs\psn\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php on line 113`

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 42 (3 by maintainers)

Most upvoted comments

I’ve updated the README to show a notice about the current state of the library. I will be working on this during the week to try to get all the bugs ironed out so we can have a working version again 😄

@Alex314Ru

        headers: {
          'Authorization' => 'Basic YWM4ZDE2MWEtZDk2Ni00NzI4LWIwZWEtZmZlYzIyZjY5ZWRjOkRFaXhFcVhYQ2RYZHdqMHY='
        },

I don’t know about safe, to be honest. After all, the API is not a public resource. I got this by reverse-engineering the PlayStation apk and it’s being used by the app.

@pacMakaveli Lifesaver - I have implemented your app endpoint approach on Node-RED finally and received the access_token and refresh_token

For those who are still struggling, a few of my learnings from @pacMakaveli code and solution

  1. The /oauth/v3/authorize endpoint needs the npsso AND ALSO Authorization headers basic token thats provided by @pacMakaveli Also note that this endpoint will try to redirect you “to the app”, however if you are using a node.js server to make the requests it will of course say the redirect “URL” is jibbrish. So make sure you disable redirects as is done in the Ruby code. And then look at the header.location where it tries to redirect you - that holds the code and cid (client_id?)

  2. The /oauth/v3/token endpoint again needs the Authorization header with the basic token and the code from /v3/authorize

So these two requests let you go from an npsso you scrape out of your manual login and arrive at a pair of access and refresh tokens which preserve access for 1h for access token and 2 months for the refresh token (which can create new access tokens for you). Or they will both become redundant when PSN does another update…

After a few hours it seems pretty clear, however I would never find those endpoints without the help of @pacMakaveli

For those whom this might help, here are the two key pieces of first-draft-code in node.js that works for me. These are written for Node-RED though, so its a bit different, but should illustrate the key points

Accessing /authorize

let npsso = msg.payload.npsso;

msg.api_params = {
    AUTH_API: 'https://ca.account.sony.com/api/authz/v3/oauth/authorize',
    CLIENT_ID: 'ac8d161a-d966-4728-b0ea-ffec22f69edc',
    SCOPE: 'psn:clientapp psn:mobile.v1'
};

msg.payload = {
    'client_id': msg.api_params.CLIENT_ID,
          'access_type': 'offline',
          'redirect_uri': 'com.playstation.PlayStationApp://redirect',
          'response_type': 'code',
          'scope': msg.api_params.SCOPE
};

msg.cookies = {
    'npsso': npsso
};


msg.headers = {
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "ca.account.sony.com",
"Referer":  "https://my.playstation.com/",
"Authorize": "Basic YWM4ZDE2MWEtZDk2Ni00NzI4LWIwZWEtZmZlYzIyZjY5ZWRjOkRFaXhFcVhYQ2RYZHdqMHY="
};

let q = "?access_type=offline";
q += "&scope=psn:clientapp psn:mobile.v1";
q += "&client_id=" + msg.api_params.CLIENT_ID;
q += "&redirect_uri=com.playstation.PlayStationApp://redirect"; //com.playstation.PlayStationApp://redirect";
q += "&response_type=code";
msg.url = msg.api_params.AUTH_API + encodeURI(q); 
msg.method = "GET";
msg.followRedirects = false;
return msg;

Accessing /token

let location = msg.headers.location;
let code = location.match(/code=([A-Za-z0-9:\?_\-\.\/=]+)/)[1];
let cid = location.match(/cid=([A-Za-z0-9:\?_\-\.\/=]+)/)[1];

msg.payload = {
    'scope': msg.api_params.SCOPE,
  'code': code,
  'grant_type': 'authorization_code',
  'redirect_uri': 'com.playstation.PlayStationApp://redirect',
  'token_format': 'jwt'
};

msg.headers = {
  'Authorization': 'Basic YWM4ZDE2MWEtZDk2Ni00NzI4LWIwZWEtZmZlYzIyZjY5ZWRjOkRFaXhFcVhYQ2RYZHdqMHY=',
  'Content-Type': "application/x-www-form-urlencoded"
};
delete msg.cookies;
msg.method = "POST";
msg.url = "https://ca.account.sony.com/api/authz/v3/oauth/token";
msg.followRedirects = true;
delete msg.statusCode;
return msg;

Thanks guys – I’ll see if I can update the current version of the library to use the new auth method. I’m still (slowly) working on the new version but I just haven’t had much time recently to focus on it. Hopefully I can finish it up soon so we can have the new API all setup when Sony inevitably deprecates the old API.

@pacMakaveli hey, i saw u took down your psn repo. do u still have the api endpoints somewhere? 🙄

I sure do! I think pretty much everything is still on postman, but I’ll share them here later as well.

Sorry, I had to make it private for personal reasons. I hope I can make them public again soon.

@pacMakaveli sorry for spamming u 😆

anyways, your XMLHttpRequest example worked, so i’m doing something wrong with axios or it just won’t work for this

Awesome to hear that! Great job with the detailed description as well. As for the cid , I can’t remember why I even extracted it to be honest. Haven’t found a use case for it so far.

For anyone still struggling, this is my Postman Workspace : https://app.getpostman.com/join-team?invite_code=86c018d31448e533a0ea3f3314f7857b where I test the endpoints. If I have some time next week I’ll organise it nicely with all the available endpoints so you’re not constricted with Ruby, PHP or Javascript syntax.

This method works for me. Sorry I can’t help with this repo but by PHP skills are long gone and I’m not familiar with this codebase. If you need some more help give me a shout and I’d be more than happy to help.

https://github.com/games-directory/api-psn/blob/master/lib/play_station_network_api/session.rb

PlayStationNetworkAPI::Session.new('npsso').authenticate