patrickbussmann / oauth2-apple

Sign in with Apple Provider for the OAuth 2.0 Client
MIT License
95 stars 64 forks source link

How to fetch users' info using token and refreshToken? #33

Closed Emad-Hamza closed 2 years ago

Emad-Hamza commented 2 years ago

Hey, I need to make subsequent authentication calls during calling 2 different APIs of mine sequentially, meaning that I need to validate the same user twice but without showing the apple UI twice. But the authorizationCode can only be used once and I can't keep the whole AppleAccessToken object and use it again in the next API call like $user = $provider->getResourceOwner($token); I understood from apple's documentation that after the first authentication call using the authorizationCode I will need to validate users' the using the refresh_token. https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens.

So in PHP it would be: $accessToken = $provider->getAccessToken('refresh_token', [ 'refresh_token' => $request->get('access_token') ]);

but the object returned does not have any of the users info, no email nor resourceOwnerId : object(League\OAuth2\Client\Token\AppleAccessToken)#6500 (8) { ["idToken":protected]=> string(709) "eyJraWQiOiJmaDZCczhDIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLmRldi10bWgubmV0c2VydmV4IiwiZXhwIjoxNjUwOTI3NjEzLCJpYXQiOjE2NTA4NDEyMTMsInN1YiI6IjAwMDkzMC40MTkxODI5ZGY5ZTM0MmYxOTQ3YjU0Zjg1MGJhMTczMy4xMjI0IiwiYXRfaGFzaCI6Ik1HcjhsOGQ2Q3RWclh1ekY3U2RIdFEiLCJlbWFpbCI6Im9tZGF0aGVvbmVAZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOiJ0cnVlIn0.OaN_3RJ40QExQeXkkVK01lzrWq5--v7jGV5Uo2jq31lmfqAWhnMXPCJAt63o6OTUScjMoP7L4-Xv95NmtbqDA3Wweq2KwxrEpr9KR2fCA60EX0kQuIycvJ7r1Djau9x0tfHrnsMS2pFo47EeayVVxOGzTMp6QFv7_ReBg3EPSboM3d0zYAq5PIiTRHzbxwCBRFk6h4gq1uv1rCnvEEhAWhPjoVYYfVm318C7uaUfJAZca8fogF7HSmZfSpXxooG9dUehGFN6RpFeCeIQ-Hg-GowztK6hE-AbUwdsiE5Y_FZHIcMokh0K_UXBJPfpmRQQmveInDQNHV8XV454ftfcyA" ["email":protected]=> NULL ["isPrivateEmail":protected]=> NULL ["accessToken":protected]=> string(63) "aad586bae625f44d8b2e48fbd8782a3ca.0.mztq.6b7AYAthn65Qw7XBxB9VSA" ["expires":protected]=> int(1650844813) ["refreshToken":protected]=> NULL ["resourceOwnerId":protected]=> NULL ["values":protected]=> array(2) { ["token_type"]=> string(6) "Bearer" ["id_token"]=> string(709) "eyJraWQiOiJmaDZCczhDIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLmRldi10bWgubmV0c2VydmV4IiwiZXhwIjoxNjUwOTI3NjEzLCJpYXQiOjE2NTA4NDEyMTMsInN1YiI6IjAwMDkzMC40MTkxODI5ZGY5ZTM0MmYxOTQ3YjU0Zjg1MGJhMTczMy4xMjI0IiwiYXRfaGFzaCI6Ik1HcjhsOGQ2Q3RWclh1ekY3U2RIdFEiLCJlbWFpbCI6Im9tZGF0aGVvbmVAZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOiJ0cnVlIn0.OaN_3RJ40QExQeXkkVK01lzrWq5--v7jGV5Uo2jq31lmfqAWhnMXPCJAt63o6OTUScjMoP7L4-Xv95NmtbqDA3Wweq2KwxrEpr9KR2fCA60EX0kQuIycvJ7r1Djau9x0tfHrnsMS2pFo47EeayVVxOGzTMp6QFv7_ReBg3EPSboM3d0zYAq5PIiTRHzbxwCBRFk6h4gq1uv1rCnvEEhAWhPjoVYYfVm318C7uaUfJAZca8fogF7HSmZfSpXxooG9dUehGFN6RpFeCeIQ-Hg-GowztK6hE-AbUwdsiE5Y_FZHIcMokh0K_UXBJPfpmRQQmveInDQNHV8XV454ftfcyA" } }

And when I try to fetch the user's info by the token that I just retrieved $fetchedUser = $client->fetchUserFromToken($accessToken); the result is the same: object(League\OAuth2\Client\Provider\AppleResourceOwner)#6512 (4) { ["response":protected]=> array(2) { ["email"]=> NULL ["isPrivateEmail"]=> NULL } ["email":"League\OAuth2\Client\Provider\AppleResourceOwner":private]=> NULL ["isPrivateEmail":"League\OAuth2\Client\Provider\AppleResourceOwner":private]=> NULL ["resourceOwnerId":protected]=> NULL }

The package's Read.me menitons using the token text in the API calls but I did not understand how: " // Use this to interact with an API on the users behalf echo $token->getToken(); "

I imagine the solution would be decoding the id_token but I do not understand yet if the JWT needed for decoding would be created in run-time or they are keys that would be configured in this package somehow.

Thanks in advance.

patrickbussmann commented 2 years ago

You only get the user info's once. So when you need it later or get it in two APIs you need to cache them manually somewhere and then get it there.

file_put_contents($accessToken, json_encode(['User-Informations']));

So its not possible to get it twice. Except Apple changed something.

Privacy is important for them 🙃