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 <[email protected]>
+
+- 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 <[email protected]>
 #
 # 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': '[email protected]',
+            '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
 
 
[email protected](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
 
 
[email protected](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': '[email protected]'
-        }],
-        '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': '[email protected]',
+        '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)
 
 
[email protected](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 = '[email protected]'
+    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': '[email protected]',
+            }
+        }
+    )
+
+    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()


Reply via email to