Hello community,
here is the log from the commit of package python-social-auth-core for openSUSE:Factory checked in at 2019-04-03 09:27:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-social-auth-core (Old)
and /work/SRC/openSUSE:Factory/.python-social-auth-core.new.25356 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-social-auth-core"
Wed Apr 3 09:27:57 2019 rev:4 rq:690607 version:3.1.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-social-auth-core/python-social-auth-core.changes 2018-12-07 14:34:06.395167424 +0100
+++ /work/SRC/openSUSE:Factory/.python-social-auth-core.new.25356/python-social-auth-core.changes 2019-04-03 09:27:58.759814229 +0200
@@ -1,0 +2,21 @@
+Tue Apr 2 10:09:14 UTC 2019 - Tomáš Chvátal
+
+- Update to 3.1.0:
+ * Universe Ticketing backend
+ * Auth0.com authentication backend
+ * Update Bungie backend dropping any Django reference
+ * Enable and fix JWT related tests
+ * Remove PyPy support from Tox
+ * Drop support for Python 3.4 in Tox
+ * Allow to override JWT decode options in Open ID Connect base backend
+ * Pass access token via Authorization header to Google user data url
+ * Updated user_data method in AzureADOAuth2 to return access_token if id_token is not present in response
+ * Updated Azure B2C to extract first email from list if it's a list
+ * Replace deprecated Google+ API usage with https://www.googleapis.com/oauth2/v3/userinfo
+ * Updated Azure Tenant to fix Nonetype error
+ * Updated comment denoting incorrect setting name
+ * Yandex: do not fail when no email is present
+ * Mediawiki: do not fail when no email is present
+ * Mediawiki: enhance get_user_details to return more details
+
+-------------------------------------------------------------------
Old:
----
social-auth-core-2.0.0.tar.gz
New:
----
social-auth-core-3.1.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-social-auth-core.spec ++++++
--- /var/tmp/diff_new_pack.7hK5X0/_old 2019-04-03 09:27:59.703814674 +0200
+++ /var/tmp/diff_new_pack.7hK5X0/_new 2019-04-03 09:27:59.703814674 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-social-auth-core
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2017-2018 Matthias Fehring
#
# All modifications and additions to the file contributed by third parties
@@ -19,20 +19,21 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-social-auth-core
-Version: 2.0.0
+Version: 3.1.0
Release: 0
Summary: Python Social Auth Core
License: BSD-3-Clause
Group: Development/Languages/Python
URL: https://github.com/python-social-auth/social-core
Source: https://files.pythonhosted.org/packages/source/s/social-auth-core/social-auth-core-%{version}.tar.gz
-BuildRequires: %{python_module PyJWT >= 1.4.0}
+BuildRequires: %{python_module PyJWT >= 1.7.1}
BuildRequires: %{python_module coverage >= 3.6}
BuildRequires: %{python_module cryptography >= 2.1.1}
BuildRequires: %{python_module httpretty}
BuildRequires: %{python_module mock}
BuildRequires: %{python_module nose >= 1.2.1}
BuildRequires: %{python_module oauthlib >= 1.0.3}
+BuildRequires: %{python_module python-jose >= 3.0.0}
BuildRequires: %{python_module rednose >= 0.4.1}
BuildRequires: %{python_module requests >= 2.9.1}
BuildRequires: %{python_module requests-oauthlib >= 0.6.1}
@@ -46,9 +47,10 @@
BuildRequires: python3 >= 3.4.0
BuildRequires: python3-defusedxml >= 0.5.0
BuildRequires: python3-python3-openid >= 3.0.10
-Requires: python-PyJWT >= 1.4.0
+Requires: python-PyJWT >= 1.7.1
Requires: python-cryptography >= 2.1.1
Requires: python-oauthlib >= 1.0.3
+Requires: python-python-jose >= 3.0.0
Requires: python-requests >= 2.9.1
Requires: python-requests-oauthlib >= 0.6.1
Requires: python-six >= 1.10.0
++++++ social-auth-core-2.0.0.tar.gz -> social-auth-core-3.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/CHANGELOG.md new/social-auth-core-3.1.0/CHANGELOG.md
--- old/social-auth-core-2.0.0/CHANGELOG.md 2018-10-28 21:20:14.000000000 +0100
+++ new/social-auth-core-3.1.0/CHANGELOG.md 2019-02-20 14:58:25.000000000 +0100
@@ -5,6 +5,35 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
+## [Unreleased](https://github.com/python-social-auth/social-core/commits/master)
+
+## [3.1.0](https://github.com/python-social-auth/social-core/releases/tag/3.1.0) - 2019-02-20
+
+### Added
+- Universe Ticketing backend
+- Auth0.com authentication backend
+
+### Changed
+- Update Bungie backend dropping any Django reference
+- Enable and fix JWT related tests
+- Remove PyPy support from Tox
+- Drop support for Python 3.4 in Tox
+- Allow to override JWT decode options in Open ID Connect base backend
+- Pass access token via Authorization header to Google user data url
+- Updated `user_data` method in `AzureADOAuth2` to return `access_token` if
+ `id_token` is not present in response
+
+## [3.0.0](https://github.com/python-social-auth/social-core/releases/tag/3.0.0) - 2019-01-14
+
+### Changed
+- Updated Azure B2C to extract first email from list if it's a list
+- Replace deprecated Google+ API usage with https://www.googleapis.com/oauth2/v3/userinfo
+- Updated Azure Tenant to fix Nonetype error
+- Updated comment denoting incorrect setting name
+- Yandex: do not fail when no email is present
+- Mediawiki: do not fail when no email is present
+- Mediawiki: enhance `get_user_details` to return more details
+
## [2.0.0](https://github.com/python-social-auth/social-core/releases/tag/2.0.0) - 2018-10-28
### Added
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/PKG-INFO new/social-auth-core-3.1.0/PKG-INFO
--- old/social-auth-core-2.0.0/PKG-INFO 2018-10-28 21:34:21.000000000 +0100
+++ new/social-auth-core-3.1.0/PKG-INFO 2019-02-20 14:59:01.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: social-auth-core
-Version: 2.0.0
+Version: 3.1.0
Summary: Python social authentication made simple.
Home-page: https://github.com/python-social-auth/social-core
Author: Matias Aguirre
@@ -60,7 +60,9 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Provides-Extra: all
Provides-Extra: openidconnect
Provides-Extra: saml
+Provides-Extra: allpy2
Provides-Extra: azuread
+Provides-Extra: allpy3
+Provides-Extra: all
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/requirements-openidconnect.txt new/social-auth-core-3.1.0/requirements-openidconnect.txt
--- old/social-auth-core-2.0.0/requirements-openidconnect.txt 2018-08-30 17:11:15.000000000 +0200
+++ new/social-auth-core-3.1.0/requirements-openidconnect.txt 2019-02-18 21:34:45.000000000 +0100
@@ -1 +1,2 @@
python-jose>=3.0.0
+pyjwt>=1.7.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/setup.py new/social-auth-core-3.1.0/setup.py
--- old/social-auth-core-2.0.0/setup.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/setup.py 2019-02-18 16:56:13.000000000 +0100
@@ -88,6 +88,8 @@
'saml': [requirements_saml],
'azuread': [requirements_azuread],
'all': [requirements_all],
+ 'allpy2': [requirements_all, requirements_py2],
+ 'allpy3': [requirements_all, requirements_py3],
':python_version < "3.0"': [requirements_py2],
':python_version >= "3.0"': [requirements_py3],
},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_auth_core.egg-info/PKG-INFO new/social-auth-core-3.1.0/social_auth_core.egg-info/PKG-INFO
--- old/social-auth-core-2.0.0/social_auth_core.egg-info/PKG-INFO 2018-10-28 21:34:21.000000000 +0100
+++ new/social-auth-core-3.1.0/social_auth_core.egg-info/PKG-INFO 2019-02-20 14:59:00.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: social-auth-core
-Version: 2.0.0
+Version: 3.1.0
Summary: Python social authentication made simple.
Home-page: https://github.com/python-social-auth/social-core
Author: Matias Aguirre
@@ -60,7 +60,9 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
-Provides-Extra: all
Provides-Extra: openidconnect
Provides-Extra: saml
+Provides-Extra: allpy2
Provides-Extra: azuread
+Provides-Extra: allpy3
+Provides-Extra: all
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_auth_core.egg-info/SOURCES.txt new/social-auth-core-3.1.0/social_auth_core.egg-info/SOURCES.txt
--- old/social-auth-core-2.0.0/social_auth_core.egg-info/SOURCES.txt 2018-10-28 21:34:21.000000000 +0100
+++ new/social-auth-core-3.1.0/social_auth_core.egg-info/SOURCES.txt 2019-02-20 14:59:01.000000000 +0100
@@ -32,6 +32,7 @@
social_core/backends/arcgis.py
social_core/backends/asana.py
social_core/backends/atlassian.py
+social_core/backends/auth0.py
social_core/backends/azuread.py
social_core/backends/azuread_b2c.py
social_core/backends/azuread_tenant.py
@@ -167,6 +168,7 @@
social_core/backends/uber.py
social_core/backends/ubuntu.py
social_core/backends/udata.py
+social_core/backends/universe.py
social_core/backends/untappd.py
social_core/backends/upwork.py
social_core/backends/username.py
@@ -222,6 +224,7 @@
social_core/tests/backends/test_arcgis.py
social_core/tests/backends/test_asana.py
social_core/tests/backends/test_atlassian.py
+social_core/tests/backends/test_auth0.py
social_core/tests/backends/test_azuread.py
social_core/tests/backends/test_azuread_b2c.py
social_core/tests/backends/test_behance.py
@@ -300,6 +303,7 @@
social_core/tests/backends/test_twitter.py
social_core/tests/backends/test_uber.py
social_core/tests/backends/test_udata.py
+social_core/tests/backends/test_universe.py
social_core/tests/backends/test_upwork.py
social_core/tests/backends/test_username.py
social_core/tests/backends/test_utils.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_auth_core.egg-info/requires.txt new/social-auth-core-3.1.0/social_auth_core.egg-info/requires.txt
--- old/social-auth-core-2.0.0/social_auth_core.egg-info/requires.txt 2018-10-28 21:34:21.000000000 +0100
+++ new/social-auth-core-3.1.0/social_auth_core.egg-info/requires.txt 2019-02-20 14:59:00.000000000 +0100
@@ -13,14 +13,31 @@
[all]
python-jose>=3.0.0
+pyjwt>=1.7.1
python-saml>=2.2.0
cryptography>=2.1.1
+[allpy2]
+python-jose>=3.0.0
+pyjwt>=1.7.1
+python-saml>=2.2.0
+cryptography>=2.1.1
+python-openid>=2.2.5
+
+[allpy3]
+python-jose>=3.0.0
+pyjwt>=1.7.1
+python-saml>=2.2.0
+cryptography>=2.1.1
+defusedxml>=0.5.0rc1
+python3-openid>=3.0.10
+
[azuread]
cryptography>=2.1.1
[openidconnect]
python-jose>=3.0.0
+pyjwt>=1.7.1
[saml]
python-saml>=2.2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/__init__.py new/social-auth-core-3.1.0/social_core/__init__.py
--- old/social-auth-core-2.0.0/social_core/__init__.py 2018-10-28 21:28:56.000000000 +0100
+++ new/social-auth-core-3.1.0/social_core/__init__.py 2019-02-20 14:57:46.000000000 +0100
@@ -1 +1 @@
-__version__ = '2.0.0'
+__version__ = '3.1.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/auth0.py new/social-auth-core-3.1.0/social_core/backends/auth0.py
--- old/social-auth-core-2.0.0/social_core/backends/auth0.py 1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.1.0/social_core/backends/auth0.py 2019-02-18 16:45:39.000000000 +0100
@@ -0,0 +1,52 @@
+"""
+Auth0 implementation based on:
+https://auth0.com/docs/quickstart/webapp/django/01-login
+"""
+from jose import jwt
+
+from .oauth import BaseOAuth2
+
+
+class Auth0OAuth2(BaseOAuth2):
+ """Auth0 OAuth authentication backend"""
+ name = 'auth0'
+ SCOPE_SEPARATOR = ' '
+ ACCESS_TOKEN_METHOD = 'POST'
+ EXTRA_DATA = [
+ ('picture', 'picture')
+ ]
+
+ def api_path(self, path=''):
+ """Build API path for Auth0 domain"""
+ return 'https://{domain}/{path}'.format(domain=self.setting('DOMAIN'),
+ path=path)
+
+ def authorization_url(self):
+ return self.api_path('authorize')
+
+ def access_token_url(self):
+ return self.api_path('oauth/token')
+
+ def get_user_id(self, details, response):
+ """Return current user id."""
+ return details['user_id']
+
+ def get_user_details(self, response):
+ # Obtain JWT and the keys to validate the signature
+ id_token = response.get('id_token')
+ jwks = self.get_json(self.api_path('.well-known/jwks.json'))
+ issuer = self.api_path()
+ audience = self.setting('KEY') # CLIENT_ID
+ payload = jwt.decode(id_token,
+ jwks,
+ algorithms=['RS256'],
+ audience=audience,
+ issuer=issuer)
+ fullname, first_name, last_name = self.get_user_names(payload['name'])
+ return {'username': payload['nickname'],
+ 'email': payload['email'],
+ 'fullname': fullname,
+ 'first_name': first_name,
+ 'last_name': last_name,
+ 'picture': payload['picture'],
+ 'user_id': payload['sub']}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/azuread.py new/social-auth-core-3.1.0/social_core/backends/azuread.py
--- old/social-auth-core-2.0.0/social_core/backends/azuread.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/azuread.py 2019-02-01 13:05:57.000000000 +0100
@@ -77,7 +77,11 @@
def user_data(self, access_token, *args, **kwargs):
response = kwargs.get('response')
- id_token = response.get('id_token')
+ if response and response.get('id_token'):
+ id_token = response.get('id_token')
+ else:
+ id_token = access_token
+
try:
decoded_id_token = jwt_decode(id_token, verify=False)
except (DecodeError, ExpiredSignature) as de:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/azuread_b2c.py new/social-auth-core-3.1.0/social_core/backends/azuread_b2c.py
--- old/social-auth-core-2.0.0/social_core/backends/azuread_b2c.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/azuread_b2c.py 2018-10-29 14:05:41.000000000 +0100
@@ -151,7 +151,9 @@
"""
details = super(AzureADB2COAuth2, self).get_user_details(response)
if not details['email'] and response.get('emails'):
- details['email'] = response['emails'][0]
+ details['email'] = response['emails']
+ if isinstance(details.get('email'), (list, tuple)):
+ details['email'] = details['email'][0]
return details
def get_public_key(self, kid):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/azuread_tenant.py new/social-auth-core-3.1.0/social_core/backends/azuread_tenant.py
--- old/social-auth-core-2.0.0/social_core/backends/azuread_tenant.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/azuread_tenant.py 2019-01-14 16:00:22.000000000 +0100
@@ -88,6 +88,10 @@
return load_pem_x509_certificate(certificate.encode(),
default_backend())
+ def get_user_id(self, details, response):
+ """Use subject (sub) claim as unique id."""
+ return response.get('sub')
+
def user_data(self, access_token, *args, **kwargs):
response = kwargs.get('response')
id_token = response.get('id_token')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/bungie.py new/social-auth-core-3.1.0/social_core/backends/bungie.py
--- old/social-auth-core-2.0.0/social_core/backends/bungie.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/bungie.py 2019-02-18 22:28:31.000000000 +0100
@@ -1,12 +1,12 @@
"""
Bungie OAuth2 backend
"""
+import requests
+
from social_core.backends.oauth import BaseOAuth2
-from django.conf import settings
class BungieOAuth2(BaseOAuth2):
-
name = 'bungie'
ID_KEY = 'membership_id'
AUTHORIZATION_URL = 'https://www.bungie.net/en/oauth/authorize/'
@@ -28,23 +28,18 @@
def auth_headers(self):
"""Adds X-API-KEY and Origin"""
- return {'X-API-KEY': settings.SOCIAL_AUTH_BUNGIE_API_KEY,
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'Origin': settings.SOCIAL_AUTH_BUNGIE_ORIGIN,
- 'Accept': 'application/json'
- }
+ return {
+ 'X-API-KEY': self.setting('API_KEY'),
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Origin': self.setting('ORIGIN'),
+ 'Accept': 'application/json'
+ }
def make_bungie_request(self, url, access_token, kwargs):
"""Helper function to get username data keyed off displayName"""
- print('ENTERING MAKE BUNGIE REQUEST')
headers = self.auth_headers()
- print(repr(headers))
- auth_header = {'Authorization': 'Bearer ' + access_token}
- headers.update(auth_header)
- import requests as python_requests
- r = python_requests.get(url, headers=headers)
- this_json = r.json()
- return this_json
+ headers['Authorization'] = 'Bearer ' + access_token
+ return self.get_json(url, headers=headers)
def auth_complete(self, *args, **kwargs):
"""Completes login process, must return user instance"""
@@ -58,7 +53,9 @@
method=self.ACCESS_TOKEN_METHOD
)
self.process_error(response)
- return self.do_auth(response['access_token'], response=response, *args, **kwargs)
+ return self.do_auth(response['access_token'],
+ response=response,
+ *args, **kwargs)
def do_auth(self, access_token, *args, **kwargs):
"""Finish the auth process once the access_token was retrieved"""
@@ -74,17 +71,16 @@
"""Grab user profile information from Bunige"""
membership_id = kwargs['response']['membership_id']
url = 'https://www.bungie.net/Platform/User/GetBungieNetUser/'
- this_json = self.make_bungie_request(url, access_token, kwargs)
- username = this_json['Response']['user']['displayName']
- return {'username': username, 'uid': membership_id}
+ response = self.make_bungie_request(url, access_token, kwargs)
+ username = response['Response']['user']['displayName']
+ return {'username': username,
+ 'uid': membership_id}
def get_user_details(self, response, *args, **kwargs):
"""Return user details from Bungie account"""
username = response['username']
- uid = response['uid']
- bnId = response['bnId']
return {
'first_name': username,
'username': username,
- 'uid': uid,
+ 'uid': response['uid'],
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/google.py new/social-auth-core-3.1.0/social_core/backends/google.py
--- old/social-auth-core-2.0.0/social_core/backends/google.py 2018-08-30 16:55:12.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/google.py 2019-02-01 13:04:34.000000000 +0100
@@ -12,7 +12,10 @@
def get_user_id(self, details, response):
"""Use google email as unique id"""
if self.setting('USE_UNIQUE_USER_ID', False):
- return response['id']
+ if 'sub' in response:
+ return response['sub']
+ else:
+ return response['id']
else:
return details['email']
@@ -20,24 +23,14 @@
"""Return user details from Google API account"""
if 'email' in response:
email = response['email']
- elif 'emails' in response:
- email = response['emails'][0]['value']
else:
email = ''
- if isinstance(response.get('name'), dict):
- names = response.get('name') or {}
- name, given_name, family_name = (
- response.get('displayName', ''),
- names.get('givenName', ''),
- names.get('familyName', '')
- )
- else:
- name, given_name, family_name = (
- response.get('name', ''),
- response.get('given_name', ''),
- response.get('family_name', '')
- )
+ name, given_name, family_name = (
+ response.get('name', ''),
+ response.get('given_name', ''),
+ response.get('family_name', ''),
+ )
fullname, first_name, last_name = self.get_user_names(
name, given_name, family_name
@@ -53,11 +46,10 @@
def user_data(self, access_token, *args, **kwargs):
"""Return user data from Google API"""
return self.get_json(
- 'https://www.googleapis.com/plus/v1/people/me',
- params={
- 'access_token': access_token,
- 'alt': 'json'
- }
+ 'https://www.googleapis.com/oauth2/v3/userinfo',
+ headers={
+ 'Authorization': 'Bearer %s' % access_token,
+ },
)
def revoke_token_params(self, token, uid):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/line.py new/social-auth-core-3.1.0/social_core/backends/line.py
--- old/social-auth-core-2.0.0/social_core/backends/line.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/line.py 2019-01-14 16:00:22.000000000 +0100
@@ -44,7 +44,6 @@
data.get('statusCode') or \
data.get('error')
error_message = data.get('errorMessage') or \
- data.get('statusMessage') or \
data.get('error_description')
if error_code is not None or error_message is not None:
raise AuthFailed(self, error_message or error_code)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/mediawiki.py new/social-auth-core-3.1.0/social_core/backends/mediawiki.py
--- old/social-auth-core-2.0.0/social_core/backends/mediawiki.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/mediawiki.py 2018-11-20 01:35:12.000000000 +0100
@@ -172,7 +172,14 @@
return {
'username': identity['username'],
- 'userID': identity['sub']
+ 'userID': identity['sub'],
+ 'email': identity.get('email'),
+ 'confirmed_email': identity.get('confirmed_email'),
+ 'editcount': identity.get('editcount'),
+ 'rights': identity.get('rights'),
+ 'groups': identity.get('groups'),
+ 'registered': identity.get('registered'),
+ 'blocked': identity.get('blocked')
}
def get_user_id(self, details, response):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/open_id_connect.py new/social-auth-core-3.1.0/social_core/backends/open_id_connect.py
--- old/social-auth-core-2.0.0/social_core/backends/open_id_connect.py 2018-08-30 17:11:15.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/open_id_connect.py 2019-02-18 21:17:43.000000000 +0100
@@ -2,10 +2,11 @@
import datetime
from calendar import timegm
+import six
from jose import jwk, jwt
from jose.jwt import JWTError, JWTClaimsError, ExpiredSignatureError
from jose.utils import base64url_decode
-import six
+
from social_core.backends.oauth import BaseOAuth2
from social_core.utils import cache
from social_core.exceptions import AuthTokenError
@@ -43,6 +44,7 @@
REVOKE_TOKEN_URL = ''
USERINFO_URL = ''
JWKS_URI = ''
+ JWT_DECODE_OPTIONS = dict()
def __init__(self, *args, **kwargs):
self.id_token = None
@@ -147,7 +149,6 @@
decoded_sig = base64url_decode(encoded_sig.encode('utf-8'))
if rsakey.verify(message.encode('utf-8'), decoded_sig):
return key
- return False
def validate_and_return_id_token(self, id_token, access_token):
"""
@@ -157,6 +158,10 @@
client_id, client_secret = self.get_key_and_secret()
key = self.find_valid_key(id_token)
+
+ if not key:
+ raise AuthTokenError(self, 'Signature verification failed')
+
alg = key['alg']
rsakey = jwk.construct(key)
@@ -167,12 +172,13 @@
algorithms=[alg],
audience=client_id,
issuer=self.id_token_issuer(),
- access_token=access_token
+ access_token=access_token,
+ options=self.JWT_DECODE_OPTIONS,
)
except ExpiredSignatureError:
raise AuthTokenError(self, 'Signature has expired')
- except JWTClaimsError:
- raise AuthTokenError(self, 'Invalid claims')
+ except JWTClaimsError as error:
+ raise AuthTokenError(self, str(error))
except JWTError:
raise AuthTokenError(self, 'Invalid signature')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/universe.py new/social-auth-core-3.1.0/social_core/backends/universe.py
--- old/social-auth-core-2.0.0/social_core/backends/universe.py 1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.1.0/social_core/backends/universe.py 2019-01-31 14:43:15.000000000 +0100
@@ -0,0 +1,35 @@
+from .oauth import BaseOAuth2
+
+
+class UniverseOAuth2(BaseOAuth2):
+ """Universe Ticketing OAuth2 authentication backend"""
+ name = 'universe'
+ AUTHORIZATION_URL = 'https://www.universe.com/oauth/authorize'
+ ACCESS_TOKEN_URL = 'https://www.universe.com/oauth/token'
+ BASE_API_URL = 'https://www.universe.com/api'
+ USER_INFO_URL = BASE_API_URL + '/v2/current_user'
+ ACCESS_TOKEN_METHOD = 'POST'
+ STATE_PARAMETER = True
+ REDIRECT_STATE = True
+ EXTRA_DATA = [
+ ('id', 'id'),
+ ('slug', 'slug'),
+ ('created_at', 'created_at'),
+ ('updated_at', 'updated_at'),
+ ]
+
+ def get_user_id(self, details, response):
+ return response['current_user'][self.ID_KEY]
+
+ def get_user_details(self, response):
+ """Return user details from a Universe account"""
+ # Start with the user data as it was returned
+ user_details = response['current_user']
+ user_details['username'] = user_details['email']
+ return user_details
+
+ def user_data(self, access_token, *args, **kwargs):
+ """Loads user data from service"""
+ return self.get_json(self.USER_INFO_URL, headers={
+ 'Authorization': 'Bearer {}'.format(access_token)
+ })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/backends/yandex.py new/social-auth-core-3.1.0/social_core/backends/yandex.py
--- old/social-auth-core-2.0.0/social_core/backends/yandex.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/backends/yandex.py 2019-01-14 16:00:22.000000000 +0100
@@ -42,9 +42,12 @@
fullname, first_name, last_name = self.get_user_names(
response.get('real_name') or response.get('display_name') or ''
)
+ email = response.get('default_email')
+ if not email:
+ emails = response.get('emails')
+ email = emails[0] if emails else ''
return {'username': response.get('display_name'),
- 'email': response.get('default_email') or
- response.get('emails', [''])[0],
+ 'email': email,
'fullname': fullname,
'first_name': first_name,
'last_name': last_name}
@@ -66,9 +69,12 @@
fullname, first_name, last_name = self.get_user_names(
response.get('real_name') or response.get('display_name') or ''
)
+ email = response.get('default_email')
+ if not email:
+ emails = response.get('emails')
+ email = emails[0] if emails else ''
return {'username': response.get('display_name'),
- 'email': response.get('default_email') or
- response.get('emails', [''])[0],
+ 'email': email,
'fullname': fullname,
'first_name': first_name,
'last_name': last_name}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/pipeline/user.py new/social-auth-core-3.1.0/social_core/pipeline/user.py
--- old/social-auth-core-2.0.0/social_core/pipeline/user.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/pipeline/user.py 2019-01-14 16:00:22.000000000 +0100
@@ -88,7 +88,7 @@
# Update user model attributes with the new data sent by the current
# provider. Update on some attributes is disabled by default, for
# example username and id fields. It's also possible to disable update
- # on fields defined in SOCIAL_AUTH_PROTECTED_FIELDS.
+ # on fields defined in SOCIAL_AUTH_PROTECTED_USER_FIELDS.
for name, value in details.items():
if value is None or not hasattr(user, name) or name in protected:
continue
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/open_id_connect.py new/social-auth-core-3.1.0/social_core/tests/backends/open_id_connect.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/open_id_connect.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/tests/backends/open_id_connect.py 2019-02-18 22:21:22.000000000 +0100
@@ -1,20 +1,14 @@
# -*- coding: utf-8 -*-
-from calendar import timegm
-
import os
import sys
import json
import datetime
import unittest2
+import base64
+from calendar import timegm
-try:
- from jwkest.jwk import RSAKey, KEYS
- from jwkest.jws import JWS
- from jwkest.jwt import b64encode_item
- NO_JWKEST = False
-except ImportError:
- NO_JWKEST = True
-
+from jose import jwt
+from jose.jwk import RSAKey
from httpretty import HTTPretty
sys.path.insert(0, '..')
@@ -22,6 +16,31 @@
from ...exceptions import AuthTokenError
+TEST_ROOT = os.path.dirname(os.path.dirname(__file__))
+
+JWK_KEY = {
+ 'kty': 'RSA',
+ 'd': 'ZmswNokEvBcxW_Kvcy8mWUQOQCBdGbnM0xR7nhvGHC-Q24z3XAQWlMWbsmGc_R1o' \
+ '_F3zK7DBlc3BokdRaO1KJirNmnHCw5TlnBlJrXiWpFBtVglUg98-4sRRO0VWnGXK' \
+ 'JPOkBQ6b_DYRO3b0o8CSpWowpiV6HB71cjXTqKPZf-aXU9WjCCAtxVjfIxgQFu5I' \
+ '-G1Qah8mZeY8HK_y99L4f0siZcbUoaIcfeWBhxi14ODyuSAHt0sNEkhiIVBZE7QZ' \
+ 'm-SEP1ryT9VAaljbwHHPmg7NC26vtLZhvaBGbTTJnEH0ZubbN2PMzsfeNyoCIHy4' \
+ '4QDSpQDCHfgcGOlHY_t5gQ',
+ 'e': 'AQAB',
+ 'use': 'sig',
+ 'kid': 'testkey',
+ 'alg': 'RS256',
+ 'n': 'pUfcJ8WFrVue98Ygzb6KEQXHBzi8HavCu8VENB2As943--bHPcQ-nScXnrRFAUg8' \
+ 'H5ZltuOcHWvsGw_AQifSLmOCSWJAPkdNb0w0QzY7Re8NrPjCsP58Tytp5LicF0Ao' \
+ 'Ag28UK3JioY9hXHGvdZsWR1Rp3I-Z3nRBP6HyO18pEgcZ91c9aAzsqu80An9X4DA' \
+ 'b1lExtZorvcd5yTBzZgr-MUeytVRni2lDNEpa6OFuopHXmg27Hn3oWAaQlbymd4g' \
+ 'ifc01oahcwl3ze2tMK6gJxa_TdCf1y99Yq6oilmVvZJ8kwWWnbPE-oDmOVPVnEyT' \
+ 'vYVCvN4rBT1DQ-x0F1mo2Q',
+}
+
+JWK_PUBLIC_KEY = {key: value for key, value in JWK_KEY.items() if key != 'd'}
+
+
class OpenIdConnectTestMixin(object):
"""
Mixin to test OpenID Connect consumers. Inheriting classes should also
@@ -35,8 +54,9 @@
def setUp(self):
super(OpenIdConnectTestMixin, self).setUp()
- test_root = os.path.dirname(os.path.dirname(__file__))
- self.key = RSAKey(kid='testkey').load(os.path.join(test_root, 'testkey.pem'))
+ self.key = JWK_KEY.copy()
+ self.public_key = JWK_PUBLIC_KEY.copy()
+
HTTPretty.register_uri(HTTPretty.GET,
self.backend.OIDC_ENDPOINT + '/.well-known/openid-configuration',
status=200,
@@ -45,14 +65,12 @@
oidc_config = json.loads(self.openid_config_body)
def jwks(_request, _uri, headers):
- ks = KEYS()
- ks.add(self.key.serialize())
- return 200, headers, ks.dump_jwks()
+ return 200, headers, json.dumps({'keys': [self.key]})
HTTPretty.register_uri(HTTPretty.GET,
oidc_config.get('jwks_uri'),
status=200,
- body=jwks)
+ body=json.dumps({'keys': [self.public_key]}))
def extra_settings(self):
settings = super(OpenIdConnectTestMixin, self).extra_settings()
@@ -64,15 +82,6 @@
})
return settings
- def access_token_body(self, request, _url, headers):
- """
- Get the nonce from the request parameters, add it to the id_token, and
- return the complete response.
- """
- nonce = self.backend.data['nonce'].encode('utf-8')
- body = self.prepare_access_token_body(nonce=nonce)
- return 200, headers, body
-
def get_id_token(self, client_key=None, expiration_datetime=None,
issue_datetime=None, nonce=None, issuer=None):
"""
@@ -110,14 +119,26 @@
nonce = nonce or 'a-nonce'
issuer = issuer or self.issuer
id_token = self.get_id_token(
- client_key, timegm(expiration_datetime.utctimetuple()),
- timegm(issue_datetime.utctimetuple()), nonce, issuer)
+ client_key,
+ timegm(expiration_datetime.utctimetuple()),
+ timegm(issue_datetime.utctimetuple()),
+ nonce,
+ issuer
+ )
+
+ body['id_token'] = jwt.encode(
+ id_token,
+ key=dict(self.key,
+ iat=timegm(issue_datetime.utctimetuple()),
+ nonce=nonce),
+ algorithm='RS256',
+ access_token='foobar'
+ )
- body['id_token'] = JWS(id_token, jwk=self.key, alg='RS256').sign_compact()
if tamper_message:
header, msg, sig = body['id_token'].split('.')
id_token['sub'] = '1235'
- msg = b64encode_item(id_token).decode('utf-8')
+ msg = base64.encodestring(json.dumps(id_token).encode()).decode()
body['id_token'] = '.'.join([header, msg, sig])
return json.dumps(body)
@@ -129,38 +150,32 @@
with self.assertRaisesRegexp(AuthTokenError, expected_message):
self.do_login()
- @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
def test_invalid_signature(self):
self.authtoken_raised(
'Token error: Signature verification failed',
tamper_message=True
)
- @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
def test_expired_signature(self):
expiration_datetime = datetime.datetime.utcnow() - \
datetime.timedelta(seconds=30)
self.authtoken_raised('Token error: Signature has expired',
expiration_datetime=expiration_datetime)
- @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
def test_invalid_issuer(self):
self.authtoken_raised('Token error: Invalid issuer',
issuer='someone-else')
- @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
def test_invalid_audience(self):
self.authtoken_raised('Token error: Invalid audience',
client_key='someone-else')
- @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
def test_invalid_issue_time(self):
expiration_datetime = datetime.datetime.utcnow() - \
datetime.timedelta(hours=1)
self.authtoken_raised('Token error: Incorrect id_token: iat',
issue_datetime=expiration_datetime)
- @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
def test_invalid_nonce(self):
self.authtoken_raised(
'Token error: Incorrect id_token: nonce',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_auth0.py new/social-auth-core-3.1.0/social_core/tests/backends/test_auth0.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_auth0.py 1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_auth0.py 2019-02-18 21:17:52.000000000 +0100
@@ -0,0 +1,68 @@
+
+import json
+
+from jose import jwt
+from httpretty import HTTPretty
+
+from .oauth import OAuth2Test
+
+JWK_KEY = {
+ 'kty': 'RSA',
+ 'd': 'ZmswNokEvBcxW_Kvcy8mWUQOQCBdGbnM0xR7nhvGHC-Q24z3XAQWlMWbsmGc_R1o' \
+ '_F3zK7DBlc3BokdRaO1KJirNmnHCw5TlnBlJrXiWpFBtVglUg98-4sRRO0VWnGXK' \
+ 'JPOkBQ6b_DYRO3b0o8CSpWowpiV6HB71cjXTqKPZf-aXU9WjCCAtxVjfIxgQFu5I' \
+ '-G1Qah8mZeY8HK_y99L4f0siZcbUoaIcfeWBhxi14ODyuSAHt0sNEkhiIVBZE7QZ' \
+ 'm-SEP1ryT9VAaljbwHHPmg7NC26vtLZhvaBGbTTJnEH0ZubbN2PMzsfeNyoCIHy4' \
+ '4QDSpQDCHfgcGOlHY_t5gQ',
+ 'e': 'AQAB',
+ 'use': 'sig',
+ 'kid': 'foobar',
+ 'alg': 'RS256',
+ 'n': 'pUfcJ8WFrVue98Ygzb6KEQXHBzi8HavCu8VENB2As943--bHPcQ-nScXnrRFAUg8' \
+ 'H5ZltuOcHWvsGw_AQifSLmOCSWJAPkdNb0w0QzY7Re8NrPjCsP58Tytp5LicF0Ao' \
+ 'Ag28UK3JioY9hXHGvdZsWR1Rp3I-Z3nRBP6HyO18pEgcZ91c9aAzsqu80An9X4DA' \
+ 'b1lExtZorvcd5yTBzZgr-MUeytVRni2lDNEpa6OFuopHXmg27Hn3oWAaQlbymd4g' \
+ 'ifc01oahcwl3ze2tMK6gJxa_TdCf1y99Yq6oilmVvZJ8kwWWnbPE-oDmOVPVnEyT' \
+ 'vYVCvN4rBT1DQ-x0F1mo2Q'
+}
+
+JWK_PUBLIC_KEY = {key: value for key, value in JWK_KEY.items() if key != 'd'}
+
+DOMAIN = 'foobar.auth0.com'
+
+
+class Auth0OAuth2Test(OAuth2Test):
+ backend_path = 'social_core.backends.auth0.Auth0OAuth2'
+ access_token_body = json.dumps({
+ 'access_token': 'foobar',
+ 'token_type': 'bearer',
+ 'expires_in': 86400,
+ 'id_token': jwt.encode({
+ 'nickname': 'foobar',
+ 'email': 'foobar@auth0.com',
+ 'name': 'John Doe',
+ 'picture': 'http://example.com/image.png',
+ 'sub': '123456',
+ 'iss': 'https://{}/'.format(DOMAIN),
+ }, JWK_KEY, algorithm='RS256')
+ })
+ expected_username = 'foobar'
+ jwks_url = 'https://foobar.auth0.com/.well-known/jwks.json'
+
+ def extra_settings(self):
+ settings = super(Auth0OAuth2Test, self).extra_settings()
+ settings['SOCIAL_AUTH_' + self.name + '_DOMAIN'] = DOMAIN
+ return settings
+
+ def auth_handlers(self, start_url):
+ HTTPretty.register_uri(HTTPretty.GET,
+ self.jwks_url,
+ body=json.dumps({'keys': [JWK_PUBLIC_KEY]}),
+ content_type='application/json')
+ return super(Auth0OAuth2Test, self).auth_handlers(start_url)
+
+ def test_login(self):
+ self.do_login()
+
+ def test_partial_pipeline(self):
+ self.do_partial_pipeline()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_azuread_b2c.py new/social-auth-core-3.1.0/social_core/tests/backends/test_azuread_b2c.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_azuread_b2c.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_azuread_b2c.py 2019-02-18 22:22:16.000000000 +0100
@@ -23,26 +23,16 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
-
-
import json
import jwt
from time import time
-from unittest import SkipTest
from httpretty import HTTPretty
+from jwt.algorithms import RSAAlgorithm
from .oauth import OAuth2Test
-try:
- from jwt.algorithms import RSAAlgorithm
-except ImportError:
- # Usually in Python 3.3
- raise SkipTest('RSA support is missing in jwt/cryptography packages')
-
-
-
# Dummy private and private keys:
RSA_PUBLIC_JWT_KEY = {
# https://github.com/jpadilla/pyjwt/blob/06f461a/tests/keys/jwk_rsa_pub.json
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_elixir.py new/social-auth-core-3.1.0/social_core/tests/backends/test_elixir.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_elixir.py 2018-10-28 20:22:07.000000000 +0100
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_elixir.py 2019-02-18 22:33:20.000000000 +0100
@@ -1,10 +1,9 @@
import unittest2
from .oauth import OAuth1Test, OAuth2Test
-from .open_id_connect import OpenIdConnectTestMixin, NO_JWKEST
+from .open_id_connect import OpenIdConnectTestMixin
-@unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
class ElixirOpenIdConnectTest(OpenIdConnectTestMixin, OAuth2Test):
backend_path = 'social_core.backends.elixir.ElixirOpenIdConnect'
issuer = 'https://login.elixir-czech.org/oidc/'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_globus.py new/social-auth-core-3.1.0/social_core/tests/backends/test_globus.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_globus.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_globus.py 2019-02-18 20:40:38.000000000 +0100
@@ -1,51 +1,49 @@
+import json
import unittest2
from .oauth import OAuth1Test, OAuth2Test
-from .open_id_connect import OpenIdConnectTestMixin, NO_JWKEST
+from .open_id_connect import OpenIdConnectTestMixin
-@unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
class GlobusOpenIdConnectTest(OpenIdConnectTestMixin, OAuth2Test):
backend_path = \
'social_core.backends.globus.GlobusOpenIdConnect'
issuer = 'https://auth.globus.org'
- openid_config_body = ''.join([
- '{'
- ' "issuer": "https://auth.globus.org",'
- ' "authorization_endpoint": "https://auth.globus.org/v2/oauth2/authorize",'
- ' "userinfo_endpoint": "https://auth.globus.org/v2/oauth2/userinfo",'
- ' "token_endpoint": "https://auth.globus.org/v2/oauth2/token",'
- ' "revocation_endpoint": "https://auth.globus.org/v2/oauth2/token/revoke",'
- ' "jwks_uri": "https://auth.globus.org/jwk.json",'
- ' "response_types_supported": ['
- ' "code",'
- ' "token",'
- ' "token id_token",'
- ' "id_token"'
- ' ],'
- ' "id_token_signing_alg_values_supported": ['
- ' "RS512"'
- ' ],'
- ' "scopes_supported": ['
- ' "openid",'
- ' "email",'
- ' "profile"'
- ' ],'
- ' "token_endpoint_auth_methods_supported": ['
- ' "client_secret_basic"'
- ' ],'
- ' "claims_supported": ['
- ' "at_hash",'
- ' "aud",'
- ' "email",'
- ' "exp",'
- ' "name",'
- ' "nonce",'
- ' "preferred_username",'
- ' "iat",'
- ' "iss",'
- ' "sub"'
- ' ],'
- ' "subject_types_supported" : ["public"]'
- '}'
- ])
+ openid_config_body = json.dumps({
+ 'issuer': 'https://auth.globus.org',
+ 'authorization_endpoint': 'https://auth.globus.org/v2/oauth2/authorize',
+ 'userinfo_endpoint': 'https://auth.globus.org/v2/oauth2/userinfo',
+ 'token_endpoint': 'https://auth.globus.org/v2/oauth2/token',
+ 'revocation_endpoint': 'https://auth.globus.org/v2/oauth2/token/revoke',
+ 'jwks_uri': 'https://auth.globus.org/jwk.json',
+ 'response_types_supported': [
+ 'code',
+ 'token',
+ 'token id_token',
+ 'id_token'
+ ],
+ 'id_token_signing_alg_values_supported': [
+ 'RS512'
+ ],
+ 'scopes_supported': [
+ 'openid',
+ 'email',
+ 'profile'
+ ],
+ 'token_endpoint_auth_methods_supported': [
+ 'client_secret_basic'
+ ],
+ 'claims_supported': [
+ 'at_hash',
+ 'aud',
+ 'email',
+ 'exp',
+ 'name',
+ 'nonce',
+ 'preferred_username',
+ 'iat',
+ 'iss',
+ 'sub'
+ ],
+ 'subject_types_supported' : ['public']
+ })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_google.py new/social-auth-core-3.1.0/social_core/tests/backends/test_google.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_google.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_google.py 2019-02-18 20:43:20.000000000 +0100
@@ -11,73 +11,40 @@
from ..models import User
from .oauth import OAuth1Test, OAuth2Test
from .open_id import OpenIdTest
-from .open_id_connect import OpenIdConnectTestMixin, NO_JWKEST
+from .open_id_connect import OpenIdConnectTestMixin
class GoogleOAuth2Test(OAuth2Test):
backend_path = 'social_core.backends.google.GoogleOAuth2'
- user_data_url = 'https://www.googleapis.com/plus/v1/people/me'
+ user_data_url = 'https://www.googleapis.com/oauth2/v3/userinfo'
expected_username = 'foo'
access_token_body = json.dumps({
'access_token': 'foobar',
'token_type': 'bearer'
})
user_data_body = json.dumps({
- 'aboutMe': 'About me text',
- 'cover': {
- 'coverInfo': {
- 'leftImageOffset': 0,
- 'topImageOffset': 0
- },
- 'coverPhoto': {
- 'height': 629,
- 'url': 'https://lh5.googleusercontent.com/-ui-GqpNh5Ms/'
- 'AAAAAAAAAAI/AAAAAAAAAZw/a7puhHMO_fg/photo.jpg',
- 'width': 940
- },
- 'layout': 'banner'
- },
- 'displayName': 'Foo Bar',
- 'emails': [{
- 'type': 'account',
- 'value': 'foo@bar.com'
- }],
- 'etag': '"e-tag string"',
- 'gender': 'male',
- 'id': '101010101010101010101',
- 'image': {
- 'url': 'https://lh5.googleusercontent.com/-ui-GqpNh5Ms/'
+ 'profile': 'https://plus.google.com/101010101010101010101',
+ 'family_name': 'Bar',
+ 'sub': '101010101010101010101',
+ 'picture': 'https://lh5.googleusercontent.com/-ui-GqpNh5Ms/'
'AAAAAAAAAAI/AAAAAAAAAZw/a7puhHMO_fg/photo.jpg',
- },
- 'isPlusUser': True,
- 'kind': 'plus#person',
- 'language': 'en',
- 'name': {
- 'familyName': 'Bar',
- 'givenName': 'Foo'
- },
- 'objectType': 'person',
- 'occupation': 'Software developer',
- 'organizations': [{
- 'name': 'Org name',
- 'primary': True,
- 'type': 'school'
- }],
- 'placesLived': [{
- 'primary': True,
- 'value': 'Anyplace'
- }],
- 'url': 'https://plus.google.com/101010101010101010101',
- 'urls': [{
- 'label': 'http://foobar.com',
- 'type': 'otherProfile',
- 'value': 'http://foobar.com',
- }],
- 'verified': False
+ 'locale': 'en',
+ 'email_verified': True,
+ 'given_name': 'Foo',
+ 'email': 'foo@bar.com',
+ 'name': 'Foo Bar',
})
def test_login(self):
self.do_login()
+ last_request = HTTPretty.last_request
+ self.assertEqual(last_request.method, 'GET')
+ self.assertTrue(self.user_data_url.endswith(last_request.path))
+ self.assertEqual(
+ last_request.headers['Authorization'],
+ 'Bearer foobar',
+ )
+ self.assertEqual(last_request.querystring, {})
def test_partial_pipeline(self):
self.do_partial_pipeline()
@@ -236,59 +203,56 @@
do_disconnect(self.backend, user)
-@unittest2.skipIf(NO_JWKEST, 'No Jwkest installed')
-class GoogleOpenIdConnectTest(OpenIdConnectTestMixin, GoogleOAuth2Test):
+class GoogleOpenIdConnectTest(OpenIdConnectTestMixin, OAuth2Test):
backend_path = \
'social_core.backends.google_openidconnect.GoogleOpenIdConnect'
user_data_url = \
'https://www.googleapis.com/plus/v1/people/me/openIdConnect'
issuer = 'accounts.google.com'
- openid_config_body = ''.join([
- '{',
- ' "issuer": "https://accounts.google.com",',
- ' "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",',
- ' "token_endpoint": "https://www.googleapis.com/oauth2/v4/token",',
- ' "userinfo_endpoint": "https://www.googleapis.com/oauth2/v3/userinfo",',
- ' "revocation_endpoint": "https://accounts.google.com/o/oauth2/revoke",',
- ' "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",',
- ' "response_types_supported": [',
- ' "code",',
- ' "token",',
- ' "id_token",',
- ' "code token",',
- ' "code id_token",',
- ' "token id_token",',
- ' "code token id_token",',
- ' "none"',
- ' ],',
- ' "subject_types_supported": [',
- ' "public"',
- ' ],',
- ' "id_token_signing_alg_values_supported": [',
- ' "RS256"',
- ' ],',
- ' "scopes_supported": [',
- ' "openid",',
- ' "email",',
- ' "profile"',
- ' ],',
- ' "token_endpoint_auth_methods_supported": [',
- ' "client_secret_post",',
- ' "client_secret_basic"',
- ' ],',
- ' "claims_supported": [',
- ' "aud",',
- ' "email",',
- ' "email_verified",',
- ' "exp",',
- ' "family_name",',
- ' "given_name",',
- ' "iat",',
- ' "iss",',
- ' "locale",',
- ' "name",',
- ' "picture",',
- ' "sub"',
- ' ]',
- '}'
- ])
+ openid_config_body = json.dumps({
+ 'issuer': 'https://accounts.google.com',
+ 'authorization_endpoint': 'https://accounts.google.com/o/oauth2/v2/auth',
+ 'token_endpoint': 'https://www.googleapis.com/oauth2/v4/token',
+ 'userinfo_endpoint': 'https://www.googleapis.com/oauth2/v3/userinfo',
+ 'revocation_endpoint': 'https://accounts.google.com/o/oauth2/revoke',
+ 'jwks_uri': 'https://www.googleapis.com/oauth2/v3/certs',
+ 'response_types_supported': [
+ 'code',
+ 'token',
+ 'id_token',
+ 'code token',
+ 'code id_token',
+ 'token id_token',
+ 'code token id_token',
+ 'none',
+ ],
+ 'subject_types_supported': [
+ 'public',
+ ],
+ 'id_token_signing_alg_values_supported': [
+ 'RS256',
+ ],
+ 'scopes_supported': [
+ 'openid',
+ 'email',
+ 'profile',
+ ],
+ 'token_endpoint_auth_methods_supported': [
+ 'client_secret_post',
+ 'client_secret_basic',
+ ],
+ 'claims_supported': [
+ 'aud',
+ 'email',
+ 'email_verified',
+ 'exp',
+ 'family_name',
+ 'given_name',
+ 'iat',
+ 'iss',
+ 'locale',
+ 'name',
+ 'picture',
+ 'sub',
+ ],
+ })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_keycloak.py new/social-auth-core-3.1.0/social_core/tests/backends/test_keycloak.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_keycloak.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_keycloak.py 2019-02-18 20:45:58.000000000 +0100
@@ -6,12 +6,6 @@
from .oauth import OAuth2Test
-try:
- from jwt.algorithms import RSAAlgorithm
-except ImportError:
- # Usually in Python 3.3
- raise unittest.SkipTest('RSA support is missing in jwt/cryptography packages')
-
_PRIVATE_KEY_HEADERLESS = '''
MIIEowIBAAKCAQEAvyo2hx1L3ALHeUd/6xk/lIhTyZ/HJZ+Sss/ge6T6gPdES4Dw
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_universe.py new/social-auth-core-3.1.0/social_core/tests/backends/test_universe.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_universe.py 1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_universe.py 2019-01-31 14:43:15.000000000 +0100
@@ -0,0 +1,32 @@
+import json
+
+from .oauth import OAuth2Test
+
+
+class UniverseAuth2Test(OAuth2Test):
+ backend_path = 'social_core.backends.universe.UniverseOAuth2'
+ user_data_url = 'https://www.universe.com/api/v2/current_user'
+ expected_username = 'scott+awesome@universe.com'
+ access_token_body = json.dumps({
+ 'access_token': 'foobar',
+ 'token_type': 'bearer'
+ })
+ user_data_body = json.dumps(
+ {
+ 'current_user': {
+ 'id': '123456',
+ 'slug': 'scott-vitale',
+ 'first_name': 'Scott',
+ 'last_name': 'Vitale',
+ 'created_at': '2019-01-08T15:49:42.514Z',
+ 'updated_at': '2019-01-17T19:41:39.711Z',
+ 'email': 'scott+awesome@universe.com',
+ }
+ }
+ )
+
+ def test_login(self):
+ self.do_login()
+
+ def test_partial_pipeline(self):
+ self.do_partial_pipeline()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/social-auth-core-2.0.0/social_core/tests/backends/test_yandex.py new/social-auth-core-3.1.0/social_core/tests/backends/test_yandex.py
--- old/social-auth-core-2.0.0/social_core/tests/backends/test_yandex.py 2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.1.0/social_core/tests/backends/test_yandex.py 2019-01-14 16:00:22.000000000 +0100
@@ -25,3 +25,31 @@
def test_partial_pipeline(self):
self.do_partial_pipeline()
+
+
+class YandexOAuth2TestEmptyEmail(OAuth2Test):
+ """
+ When user log in to yandex service with social network account (e.g.
+ vk.com), they `default_email` could be empty.
+ """
+ backend_path = 'social_core.backends.yandex.YandexOAuth2'
+ user_data_url = 'https://login.yandex.ru/info'
+ expected_username = 'foobar'
+ access_token_body = json.dumps({
+ 'access_token': 'foobar',
+ 'token_type': 'bearer'
+ })
+ user_data_body = json.dumps({
+ 'display_name': 'foobar',
+ 'real_name': 'Foo Bar',
+ 'sex': None,
+ 'id': '101010101',
+ 'default_email': '',
+ 'emails': []
+ })
+
+ def test_login(self):
+ self.do_login()
+
+ def test_partial_pipeline(self):
+ self.do_partial_pipeline()