auth: Expect name in request params in Apple auth.

The name used to be included in the id_token, but this seems to have
been changed by Apple and now it's sent in the `user` request param.

https://github.com/python-social-auth/social-core/pull/483 is the
upstream PR for this - but upstream is currently unmaintained, so we
have to monkey patch.

We also alter the tests to reflect this situation. Tests no longer put
the name in the id_token, but rather in the `user` request param in the
browser flow, just like it happens in reality.

An adaptation has to be made in the native flow - since the name won't
be included by Apple in the id_token anymore, the app, when POSTing
to the /complete/apple/ endpoint,
can (and should for better user experience)
add the `user` param formatted as json of
{"email": "hamlet@zulip.com", "name": {"firstName": "Full", "lastName": "Name"}}
dict. This is also reflected by the change in the
native flow tests.
This commit is contained in:
Mateusz Mandera
2020-10-22 19:24:19 +02:00
committed by Tim Abbott
parent 0ea20bd7d8
commit 48f80fcb0a
2 changed files with 38 additions and 4 deletions

View File

@@ -1643,6 +1643,33 @@ class AppleAuthBackend(SocialAuthMixin, AppleIdAuth):
self.strategy.session_set(param, value)
return request_state
def get_user_details(self, response: Dict[str, Any]) -> Dict[str, Any]:
"""
Overriden to correctly grab the user's name from the request params,
as current upstream code expects it in the id_token and Apple changed
the API.
Taken from https://github.com/python-social-auth/social-core/pull/483
TODO: Remove this when the PR is merged.
"""
name = response.get('name') or {}
name = json.loads(self.data.get('user', '{}')).get('name', {})
fullname, first_name, last_name = self.get_user_names(
fullname='',
first_name=name.get('firstName', ''),
last_name=name.get('lastName', '')
)
email = response.get('email', '')
# prevent updating User with empty strings
user_details = {
'fullname': fullname or None,
'first_name': first_name or None,
'last_name': last_name or None,
'email': email,
}
user_details['username'] = email
return user_details
def auth_complete(self, *args: Any, **kwargs: Any) -> Optional[HttpResponse]:
if not self.is_native_flow():
# The default implementation in python-social-auth is the browser flow.