Hello community,
here is the log from the commit of package python-social-auth-core for
openSUSE:Factory checked in at 2019-06-03 18:57:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-social-auth-core (Old)
and /work/SRC/openSUSE:Factory/.python-social-auth-core.new.5148 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-social-auth-core"
Mon Jun 3 18:57:53 2019 rev:7 rq:707119 version:3.2.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-social-auth-core/python-social-auth-core.changes
2019-05-06 13:21:40.240574315 +0200
+++
/work/SRC/openSUSE:Factory/.python-social-auth-core.new.5148/python-social-auth-core.changes
2019-06-03 18:57:56.288371710 +0200
@@ -1,0 +2,8 @@
+Mon Jun 3 10:08:47 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 3.2.0:
+ * Cognito backend
+ * OpenStack (openstackid and openstackid-dev) backends
+ * Many fixes to all existing Backends to match up upstream projects
+
+-------------------------------------------------------------------
Old:
----
social-auth-core-3.1.0.tar.gz
New:
----
social-auth-core-3.2.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-social-auth-core.spec ++++++
--- /var/tmp/diff_new_pack.zbP2Tg/_old 2019-06-03 18:57:57.420371289 +0200
+++ /var/tmp/diff_new_pack.zbP2Tg/_new 2019-06-03 18:57:57.420371289 +0200
@@ -19,7 +19,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-social-auth-core
-Version: 3.1.0
+Version: 3.2.0
Release: 0
Summary: Python Social Auth Core
License: BSD-3-Clause
++++++ social-auth-core-3.1.0.tar.gz -> social-auth-core-3.2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/CHANGELOG.md
new/social-auth-core-3.2.0/CHANGELOG.md
--- old/social-auth-core-3.1.0/CHANGELOG.md 2019-02-20 14:58:25.000000000
+0100
+++ new/social-auth-core-3.2.0/CHANGELOG.md 2019-05-30 07:07:03.000000000
+0200
@@ -7,6 +7,29 @@
##
[Unreleased](https://github.com/python-social-auth/social-core/commits/master)
+##
[3.2.0](https://github.com/python-social-auth/social-core/releases/tag/3.2.0) -
2019-05-30
+
+### Added
+- Cognito backend
+- OpenStack (openstackid and openstackid-dev) backends
+
+### Changed
+- Updated Linkedin backend to v2 API
+- Facebook: Update to use the latest Graph API v3.2
+- Send User-Agent header on GitHub backend
+- Remove profile scope and verification at hash on Elixir backend
+- Mark description as Markdown for PyPI
+- Use `hmac.compare_digest` for constant time comparision
+- Replace deprecated Google+ API usage in GoogleOpenIdConnect
+- Defined scope separator for Strava backend
+- Ensure `saml_config.json` is included by addint it to `MANIFEST.in`
+- Include `email_verified` as part of user details on Auth0 backend
+- Include Shopify `version` parameter on Shopify session setup
+- Define `SOCIAL_AUTH_SHOPIFY_API_VERSION` setting to override default API
version
+- Check user `id` attribute existence before using it
+- Pull `last_name` from `family_name` in Cognito backend
+- Ignore key errors on Naver backend for missing attributes
+
##
[3.1.0](https://github.com/python-social-auth/social-core/releases/tag/3.1.0) -
2019-02-20
### Added
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/MANIFEST.in
new/social-auth-core-3.2.0/MANIFEST.in
--- old/social-auth-core-3.1.0/MANIFEST.in 2018-08-20 15:44:10.000000000
+0200
+++ new/social-auth-core-3.2.0/MANIFEST.in 2019-04-21 15:29:41.000000000
+0200
@@ -1,7 +1,7 @@
global-include *.py
include *.txt CHANGELOG.md LICENSE README.md social_core/tests/testkey.pem
-recursive-include social_core/tests *.txt
+recursive-include social_core/tests *.txt *.json
graft examples
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/PKG-INFO
new/social-auth-core-3.2.0/PKG-INFO
--- old/social-auth-core-3.1.0/PKG-INFO 2019-02-20 14:59:01.000000000 +0100
+++ new/social-auth-core-3.2.0/PKG-INFO 2019-05-30 07:09:54.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: social-auth-core
-Version: 3.1.0
+Version: 3.2.0
Summary: Python social authentication made simple.
Home-page: https://github.com/python-social-auth/social-core
Author: Matias Aguirre
@@ -60,9 +60,10 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
+Description-Content-Type: text/markdown
Provides-Extra: openidconnect
-Provides-Extra: saml
Provides-Extra: allpy2
Provides-Extra: azuread
-Provides-Extra: allpy3
Provides-Extra: all
+Provides-Extra: saml
+Provides-Extra: allpy3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/setup.py
new/social-auth-core-3.2.0/setup.py
--- old/social-auth-core-3.1.0/setup.py 2019-02-18 16:56:13.000000000 +0100
+++ new/social-auth-core-3.2.0/setup.py 2019-04-07 15:28:25.000000000 +0200
@@ -82,6 +82,7 @@
'social_core.tests.backends.data'
],
long_description=long_description() or LONG_DESCRIPTION,
+ long_description_content_type="text/markdown",
install_requires=requirements,
extras_require={
'openidconnect': [requirements_openidconnect],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_auth_core.egg-info/PKG-INFO
new/social-auth-core-3.2.0/social_auth_core.egg-info/PKG-INFO
--- old/social-auth-core-3.1.0/social_auth_core.egg-info/PKG-INFO
2019-02-20 14:59:00.000000000 +0100
+++ new/social-auth-core-3.2.0/social_auth_core.egg-info/PKG-INFO
2019-05-30 07:09:53.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: social-auth-core
-Version: 3.1.0
+Version: 3.2.0
Summary: Python social authentication made simple.
Home-page: https://github.com/python-social-auth/social-core
Author: Matias Aguirre
@@ -60,9 +60,10 @@
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
+Description-Content-Type: text/markdown
Provides-Extra: openidconnect
-Provides-Extra: saml
Provides-Extra: allpy2
Provides-Extra: azuread
-Provides-Extra: allpy3
Provides-Extra: all
+Provides-Extra: saml
+Provides-Extra: allpy3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_auth_core.egg-info/SOURCES.txt
new/social-auth-core-3.2.0/social_auth_core.egg-info/SOURCES.txt
--- old/social-auth-core-3.1.0/social_auth_core.egg-info/SOURCES.txt
2019-02-20 14:59:01.000000000 +0100
+++ new/social-auth-core-3.2.0/social_auth_core.egg-info/SOURCES.txt
2019-05-30 07:09:54.000000000 +0200
@@ -49,6 +49,7 @@
social_core/backends/classlink.py
social_core/backends/clef.py
social_core/backends/coding.py
+social_core/backends/cognito.py
social_core/backends/coinbase.py
social_core/backends/coursera.py
social_core/backends/dailymotion.py
@@ -121,6 +122,8 @@
social_core/backends/open_id.py
social_core/backends/open_id_connect.py
social_core/backends/openshift.py
+social_core/backends/openstack.py
+social_core/backends/openstackdev.py
social_core/backends/openstreetmap.py
social_core/backends/orbi.py
social_core/backends/orcid.py
@@ -233,6 +236,7 @@
social_core/tests/backends/test_broken.py
social_core/tests/backends/test_chatwork.py
social_core/tests/backends/test_clef.py
+social_core/tests/backends/test_cognito.py
social_core/tests/backends/test_coinbase.py
social_core/tests/backends/test_coursera.py
social_core/tests/backends/test_dailymotion.py
@@ -314,4 +318,5 @@
social_core/tests/backends/test_yammer.py
social_core/tests/backends/test_yandex.py
social_core/tests/backends/test_zotero.py
+social_core/tests/backends/data/saml_config.json
social_core/tests/backends/data/saml_response.txt
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/social_core/__init__.py
new/social-auth-core-3.2.0/social_core/__init__.py
--- old/social-auth-core-3.1.0/social_core/__init__.py 2019-02-20
14:57:46.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/__init__.py 2019-05-30
07:06:39.000000000 +0200
@@ -1 +1 @@
-__version__ = '3.1.0'
+__version__ = '3.2.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/social_core/backends/auth0.py
new/social-auth-core-3.2.0/social_core/backends/auth0.py
--- old/social-auth-core-3.1.0/social_core/backends/auth0.py 2019-02-18
16:45:39.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/backends/auth0.py 2019-04-21
15:34:42.000000000 +0200
@@ -45,6 +45,7 @@
fullname, first_name, last_name = self.get_user_names(payload['name'])
return {'username': payload['nickname'],
'email': payload['email'],
+ 'email_verified': payload.get('email_verified', False),
'fullname': fullname,
'first_name': first_name,
'last_name': last_name,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/cognito.py
new/social-auth-core-3.2.0/social_core/backends/cognito.py
--- old/social-auth-core-3.1.0/social_core/backends/cognito.py 1970-01-01
01:00:00.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/backends/cognito.py 2019-05-30
06:45:47.000000000 +0200
@@ -0,0 +1,51 @@
+from social_core.backends.oauth import BaseOAuth2
+
+
+class CognitoOAuth2(BaseOAuth2):
+ name = 'cognito'
+ ID_KEY = 'username'
+ DEFAULT_SCOPE = ['openid', 'profile', 'email']
+ ACCESS_TOKEN_METHOD = 'POST'
+ REDIRECT_STATE = False
+
+ def user_pool_domain(self):
+ return self.setting('POOL_DOMAIN')
+
+ def authorization_url(self):
+ return '{}/login'.format(self.user_pool_domain())
+
+ def access_token_url(self):
+ return '{}/oauth2/token'.format(self.user_pool_domain())
+
+ def user_data_url(self):
+ return '{}/oauth2/userInfo'.format(self.user_pool_domain())
+
+ def get_user_details(self, response):
+ """Return user details from their cognito pool account"""
+ first_name = response.get('given_name') or ''
+ last_name = response.get('family_name') or ''
+ fullname, first_name, last_name = self.get_user_names(
+ first_name=first_name,
+ last_name=last_name,
+ )
+ return {'username': response.get('username') or response.get('email'),
+ 'email': response.get('email'),
+ 'fullname': fullname,
+ 'first_name': first_name,
+ 'last_name': last_name}
+
+ def user_data(self, access_token, *args, **kwargs):
+ """Grab user profile information from cognito."""
+ response = self.get_json(
+ url=self.user_data_url(),
+ headers={'Authorization': 'Bearer {}'.format(access_token)},
+ )
+
+ user_data = {
+ 'given_name': response.get('given_name'),
+ 'family_name': response.get('family_name'),
+ 'username': response.get('username'),
+ 'email': response.get('email'),
+ }
+
+ return user_data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/elixir.py
new/social-auth-core-3.2.0/social_core/backends/elixir.py
--- old/social-auth-core-3.1.0/social_core/backends/elixir.py 2018-10-28
20:22:07.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/backends/elixir.py 2019-04-07
15:28:25.000000000 +0200
@@ -15,6 +15,11 @@
('id_token', 'id_token', True),
('other_tokens', 'other_tokens', True),
]
+ # In order to get any scopes, you have to register your service with
+ # ELIXIR, see documentation at
+ # https://www.elixir-europe.org/services/compute/aai
+ DEFAULT_SCOPE = ['openid', 'email']
+ JWT_DECODE_OPTIONS = {'verify_at_hash': False}
def get_user_details(self, response):
username_key = self.setting('USERNAME_KEY', default=self.USERNAME_KEY)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/facebook.py
new/social-auth-core-3.2.0/social_core/backends/facebook.py
--- old/social-auth-core-3.1.0/social_core/backends/facebook.py 2018-08-30
16:55:12.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/backends/facebook.py 2019-04-10
14:14:40.000000000 +0200
@@ -14,7 +14,7 @@
AuthMissingParameter
-API_VERSION = 2.9
+API_VERSION = 3.2
class FacebookOAuth2(BaseOAuth2):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/github.py
new/social-auth-core-3.2.0/social_core/backends/github.py
--- old/social-auth-core-3.1.0/social_core/backends/github.py 2018-08-20
15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/backends/github.py 2019-04-07
15:28:25.000000000 +0200
@@ -20,6 +20,7 @@
SCOPE_SEPARATOR = ','
REDIRECT_STATE = False
STATE_PARAMETER = True
+ SEND_USER_AGENT = True
EXTRA_DATA = [
('id', 'id'),
('expires', 'expires'),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/google_openidconnect.py
new/social-auth-core-3.2.0/social_core/backends/google_openidconnect.py
--- old/social-auth-core-3.1.0/social_core/backends/google_openidconnect.py
2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/backends/google_openidconnect.py
2019-04-07 15:28:25.000000000 +0200
@@ -16,6 +16,6 @@
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/openIdConnect',
+ 'https://openidconnect.googleapis.com/v1/userinfo',
params={'access_token': access_token, 'alt': 'json'}
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/linkedin.py
new/social-auth-core-3.2.0/social_core/backends/linkedin.py
--- old/social-auth-core-3.1.0/social_core/backends/linkedin.py 2018-08-20
15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/backends/linkedin.py 2019-04-07
14:33:19.000000000 +0200
@@ -2,94 +2,108 @@
LinkedIn OAuth1 and OAuth2 backend, docs at:
https://python-social-auth.readthedocs.io/en/latest/backends/linkedin.html
"""
-from .oauth import BaseOAuth1, BaseOAuth2
+from social_core.exceptions import AuthCanceled
+from .oauth import BaseOAuth2
-class BaseLinkedinAuth(object):
- EXTRA_DATA = [('id', 'id'),
- ('expires_in', 'expires'),
- ('first-name', 'first_name', True),
- ('last-name', 'last_name', True),
- ('firstName', 'first_name', True),
- ('lastName', 'last_name', True)]
- USER_DETAILS = 'https://api.linkedin.com/v1/people/~:({0})'
-
- def get_user_details(self, response):
- """Return user details from Linkedin account"""
- fullname, first_name, last_name = self.get_user_names(
- first_name=response['firstName'],
- last_name=response['lastName']
- )
- email = response.get('emailAddress', '')
- return {'username': first_name + last_name,
- 'fullname': fullname,
- 'first_name': first_name,
- 'last_name': last_name,
- 'email': email}
+class LinkedinOAuth2(BaseOAuth2):
+ name = 'linkedin-oauth2'
+ AUTHORIZATION_URL = \
+ 'https://www.linkedin.com/oauth/v2/authorization'
+ ACCESS_TOKEN_URL = 'https://www.linkedin.com/oauth/v2/accessToken'
+ USER_DETAILS_URL = \
+ 'https://api.linkedin.com/v2/me?projection=({projection})'
+ USER_EMAILS_URL = 'https://api.linkedin.com/v2/emailAddress' \
+ '?q=members&projection=(elements*(handle~))'
+ ACCESS_TOKEN_METHOD = 'POST'
+ REDIRECT_STATE = False
+ DEFAULT_SCOPE = ['r_liteprofile']
+ EXTRA_DATA = [
+ ('id', 'id'),
+ ('expires_in', 'expires'),
+ ('firstName', 'first_name'),
+ ('lastName', 'last_name')
+ ]
def user_details_url(self):
# use set() since LinkedIn fails when values are duplicated
- fields_selectors = list(set(['first-name', 'id', 'last-name'] +
- self.setting('FIELD_SELECTORS', [])))
+ fields_selectors = list(set(['id', 'firstName', 'lastName'] +
+ self.setting('FIELD_SELECTORS', [])))
# user sort to ease the tests URL mocking
fields_selectors.sort()
fields_selectors = ','.join(fields_selectors)
- return self.USER_DETAILS.format(fields_selectors)
+ return self.USER_DETAILS_URL.format(projection=fields_selectors)
- def user_data_headers(self):
- lang = self.setting('FORCE_PROFILE_LANGUAGE')
- if lang:
- return {
- 'Accept-Language': lang if lang is not True
- else self.strategy.get_language()
- }
-
-
-class LinkedinOAuth(BaseLinkedinAuth, BaseOAuth1):
- """Linkedin OAuth authentication backend"""
- name = 'linkedin'
- SCOPE_SEPARATOR = '+'
- AUTHORIZATION_URL = 'https://www.linkedin.com/uas/oauth/authenticate'
- REQUEST_TOKEN_URL = 'https://api.linkedin.com/uas/oauth/requestToken'
- ACCESS_TOKEN_URL = 'https://api.linkedin.com/uas/oauth/accessToken'
+ def user_emails_url(self):
+ return self.USER_EMAILS_URL
def user_data(self, access_token, *args, **kwargs):
- """Return user data provided"""
- return self.get_json(
+ response = self.get_json(
self.user_details_url(),
- params={'format': 'json'},
- auth=self.oauth_auth(access_token),
- headers=self.user_data_headers()
+ headers=self.user_data_headers(access_token)
)
- def unauthorized_token(self):
- """Makes first request to oauth. Returns an unauthorized Token."""
- scope = self.get_scope() or ''
- if scope:
- scope = '?scope=' + self.SCOPE_SEPARATOR.join(scope)
- return self.request(self.REQUEST_TOKEN_URL + scope,
- params=self.request_token_extra_arguments(),
- auth=self.oauth_auth()).text
+ if 'emailAddress' in set(self.setting('FIELD_SELECTORS', [])):
+ emails = self.email_data(access_token, *args, **kwargs)
+ if emails:
+ response['emailAddress'] = emails[0]
+
+ return response
+
+ def email_data(self, access_token, *args, **kwargs):
+ response = self.get_json(
+ self.user_emails_url(),
+ headers=self.user_data_headers(access_token)
+ )
+ email_addresses = []
+ for element in response.get('elements', []):
+ email_address = element.get('handle~', {}).get('emailAddress')
+ email_addresses.append(email_address)
+ return list(filter(None, email_addresses))
+ def get_user_details(self, response):
+ """Return user details from Linkedin account"""
-class LinkedinOAuth2(BaseLinkedinAuth, BaseOAuth2):
- name = 'linkedin-oauth2'
- SCOPE_SEPARATOR = ' '
- AUTHORIZATION_URL = 'https://www.linkedin.com/uas/oauth2/authorization'
- ACCESS_TOKEN_URL = 'https://www.linkedin.com/uas/oauth2/accessToken'
- ACCESS_TOKEN_METHOD = 'POST'
- REDIRECT_STATE = False
+ def get_localized_name(name):
+ """
+ FirstName & Last Name object
+ {
+ "localized":{
+ "en_US":"Smith"
+ },
+ "preferredLocale":{
+ "country":"US",
+ "language":"en"
+ }
+ }
+ :return the localizedName from the lastName object
+ """
+ locale = "{}_{}".format(
+ name["preferredLocale"]["language"],
+ name["preferredLocale"]["country"]
+ )
+ return name['localized'].get(locale, '')
- def user_data(self, access_token, *args, **kwargs):
- headers = self.user_data_headers() or {}
- headers['Authorization'] = 'Bearer {access_token}'.format(
- access_token=access_token
- )
- return self.get_json(
- self.user_details_url(),
- params={'format': 'json'},
- headers=headers
+ fullname, first_name, last_name = self.get_user_names(
+ first_name=get_localized_name(response['firstName']),
+ last_name=get_localized_name(response['lastName'])
)
+ email = response.get('emailAddress', '')
+ return {'username': first_name + last_name,
+ 'fullname': fullname,
+ 'first_name': first_name,
+ 'last_name': last_name,
+ 'email': email}
+
+ def user_data_headers(self, access_token):
+ headers = {}
+ lang = self.setting('FORCE_PROFILE_LANGUAGE')
+ if lang:
+ headers['Accept-Language'] = lang if lang is not True \
+ else self.strategy.get_language()
+ headers['Authorization'] = 'Bearer {access_token}'.format(
+ access_token=access_token)
+ return headers
def request_access_token(self, *args, **kwargs):
# LinkedIn expects a POST request with querystring parameters, despite
@@ -99,18 +113,17 @@
*args, **kwargs
)
+ def process_error(self, data):
+ super(LinkedinOAuth2, self).process_error(data)
+ if data.get('serviceErrorCode'):
+ raise AuthCanceled(self, data.get('message') or data.get('status'))
+
class LinkedinMobileOAuth2(LinkedinOAuth2):
name = 'linkedin-mobile-oauth2'
- def user_data(self, access_token, *args, **kwargs):
- headers = self.user_data_headers()
- if not headers:
- headers = {}
- headers['Authorization'] = 'Bearer ' + access_token
+ def user_data_headers(self, access_token):
+ headers = super(LinkedinMobileOAuth2, self).user_data_headers(
+ access_token)
headers['x-li-src'] = 'msdk'
- return self.get_json(
- self.user_details_url(),
- params={'format': 'json'},
- headers=headers
- )
+ return headers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/social_core/backends/naver.py
new/social-auth-core-3.2.0/social_core/backends/naver.py
--- old/social-auth-core-3.1.0/social_core/backends/naver.py 2018-08-20
15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/backends/naver.py 2019-05-30
06:50:11.000000000 +0200
@@ -57,4 +57,8 @@
}
def _dom_value(self, dom, key):
- return dom.getElementsByTagName(key)[0].childNodes[0].data
+ try:
+ # Fixed Missing Key Getting Error
+ return dom.getElementsByTagName(key)[0].childNodes[0].data
+ except IndexError:
+ return ''
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/openstack.py
new/social-auth-core-3.2.0/social_core/backends/openstack.py
--- old/social-auth-core-3.1.0/social_core/backends/openstack.py
1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/backends/openstack.py
2019-05-30 06:58:33.000000000 +0200
@@ -0,0 +1,47 @@
+"""
+OpenStack OpenId backend
+"""
+from six.moves.urllib_parse import urlsplit
+from openid.extensions import ax
+
+from .open_id import OpenIdAuth
+
+
+class OpenStackOpenId(OpenIdAuth):
+ name = 'openstack'
+ URL = 'openstackid.org'
+
+ def get_user_details(self, response):
+ """Generate username from identity url"""
+ values = super(OpenStackDevOpenId, self).get_user_details(response)
+ values['username'] = values.get('username') or \
+ urlsplit(response.identity_url).path.strip('/')
+ values['nickname'] = values.get('nickname', '')
+ return values
+
+ def setup_request(self, params=None):
+ """Fetch email, firstname, lastname from openid"""
+ request = self.openid_request(params)
+
+ # TODO: use sreg instead ax request to fetch nickname as username
+ fetch_request = ax.FetchRequest()
+ fetch_request.add(ax.AttrInfo(
+ 'http://axschema.org/contact/email',
+ alias='email',
+ required=True
+ ))
+
+ fetch_request.add(ax.AttrInfo(
+ 'http://axschema.org/namePerson/first',
+ alias='firstname',
+ required=True
+ ))
+
+ fetch_request.add(ax.AttrInfo(
+ 'http://axschema.org/namePerson/last',
+ alias='lastname',
+ required=True
+ ))
+
+ request.addExtension(fetch_request)
+ return request
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/openstackdev.py
new/social-auth-core-3.2.0/social_core/backends/openstackdev.py
--- old/social-auth-core-3.1.0/social_core/backends/openstackdev.py
1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/backends/openstackdev.py
2019-05-30 06:58:33.000000000 +0200
@@ -0,0 +1,47 @@
+"""
+OpenStack OpenId backend
+"""
+from six.moves.urllib_parse import urlsplit
+from openid.extensions import ax
+
+from .open_id import OpenIdAuth
+
+
+class OpenStackDevOpenId(OpenIdAuth):
+ name = 'openstackdev'
+ URL = 'openstackid-dev.openstack.org'
+
+ def get_user_details(self, response):
+ """Generate username from identity url"""
+ values = super(OpenStackDevOpenId, self).get_user_details(response)
+ values['username'] = values.get('username') or \
+ urlsplit(response.identity_url).path.strip('/')
+ values['nickname'] = values.get('nickname', '')
+ return values
+
+ def setup_request(self, params=None):
+ """Fetch email, firstname, lastname from openid"""
+ request = self.openid_request(params)
+
+ # TODO: use sreg instead ax request to fetch nickname as username
+ fetch_request = ax.FetchRequest()
+ fetch_request.add(ax.AttrInfo(
+ 'http://axschema.org/contact/email',
+ alias='email',
+ required=True
+ ))
+
+ fetch_request.add(ax.AttrInfo(
+ 'http://axschema.org/namePerson/first',
+ alias='firstname',
+ required=True
+ ))
+
+ fetch_request.add(ax.AttrInfo(
+ 'http://axschema.org/namePerson/last',
+ alias='lastname',
+ required=True
+ ))
+
+ request.addExtension(fetch_request)
+ return request
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/shopify.py
new/social-auth-core-3.2.0/social_core/backends/shopify.py
--- old/social-auth-core-3.1.0/social_core/backends/shopify.py 2018-08-20
15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/backends/shopify.py 2019-04-22
17:26:10.000000000 +0200
@@ -22,7 +22,11 @@
REDIRECT_STATE = False
@property
- def shopifyAPI(self):
+ def shopify_api_version(self):
+ return self.setting('API_VERSION', '2019-04')
+
+ @property
+ def shopify_api(self):
if not hasattr(self, '_shopify_api'):
fp, pathname, description = imp.find_module('shopify')
self._shopify_api = imp.load_module('shopify', fp, pathname,
@@ -42,7 +46,8 @@
extra_data field"""
data = super(ShopifyOAuth2, self).extra_data(user, uid, response,
details, *args, **kwargs)
- session = self.shopifyAPI.Session(self.data.get('shop').strip())
+ session = self.shopify_api.Session(self.data.get('shop').strip(),
+ version=self.shopify_api_version)
# Get, and store the permanent token
token = session.request_token(data['access_token'])
data['access_token'] = token
@@ -50,12 +55,13 @@
def auth_url(self):
key, secret = self.get_key_and_secret()
- self.shopifyAPI.Session.setup(api_key=key, secret=secret)
+ self.shopify_api.Session.setup(api_key=key, secret=secret)
scope = self.get_scope()
state = self.state_token()
self.strategy.session_set(self.name + '_state', state)
redirect_uri = self.get_redirect_uri(state)
- session = self.shopifyAPI.Session(self.data.get('shop').strip())
+ session = self.shopify_api.Session(self.data.get('shop').strip(),
+ version=self.shopify_api_version)
return session.create_permission_url(
scope=scope,
redirect_uri=redirect_uri
@@ -69,10 +75,12 @@
key, secret = self.get_key_and_secret()
try:
shop_url = self.data.get('shop')
- self.shopifyAPI.Session.setup(api_key=key, secret=secret)
- shopify_session = self.shopifyAPI.Session(shop_url, self.data)
+ self.shopify_api.Session.setup(api_key=key, secret=secret)
+ shopify_session = self.shopify_api.Session(
+ shop_url, version=self.shopify_api_version, token=self.data
+ )
access_token = shopify_session.token
- except self.shopifyAPI.ValidationException:
+ except self.shopify_api.ValidationException:
raise AuthCanceled(self)
else:
if not access_token:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/backends/strava.py
new/social-auth-core-3.2.0/social_core/backends/strava.py
--- old/social-auth-core-3.1.0/social_core/backends/strava.py 2018-08-20
15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/backends/strava.py 2019-04-21
15:17:43.000000000 +0200
@@ -16,6 +16,7 @@
# Check issue #259 for details.
REDIRECT_STATE = False
REVOKE_TOKEN_URL = 'https://www.strava.com/oauth/deauthorize'
+ SCOPE_SEPARATOR = ','
def get_user_id(self, details, response):
return response['athlete']['id']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/social_core/pipeline/utils.py
new/social-auth-core-3.2.0/social_core/pipeline/utils.py
--- old/social-auth-core-3.1.0/social_core/pipeline/utils.py 2018-08-20
15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/pipeline/utils.py 2019-05-30
06:41:39.000000000 +0200
@@ -23,7 +23,7 @@
'uid': kwargs.get('uid'),
'is_new': kwargs.get('is_new') or False,
'new_association': kwargs.get('new_association') or False,
- 'user': user and user.id or None,
+ 'user': hasattr(user, 'id') and user.id or None,
'social': social and {
'provider': social.provider,
'uid': social.uid
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/tests/backends/data/saml_config.json
new/social-auth-core-3.2.0/social_core/tests/backends/data/saml_config.json
--- old/social-auth-core-3.1.0/social_core/tests/backends/data/saml_config.json
1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/tests/backends/data/saml_config.json
2018-08-20 15:44:10.000000000 +0200
@@ -0,0 +1,23 @@
+{
+ "SOCIAL_AUTH_SAML_SP_ENTITY_ID":
"https://github.com/omab/python-social-auth/saml-test",
+ "SOCIAL_AUTH_SAML_SP_PUBLIC_CERT":
"MIICsDCCAhmgAwIBAgIJAO7BwdjDZcUWMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNBMRkwFwYDVQQIExBCcml0aXNoIENvbHVtYmlhMRswGQYDVQQKExJweXRob24tc29jaWFsLWF1dGgwHhcNMTUwNTA4MDc1ODQ2WhcNMjUwNTA3MDc1ODQ2WjBFMQswCQYDVQQGEwJDQTEZMBcGA1UECBMQQnJpdGlzaCBDb2x1bWJpYTEbMBkGA1UEChMScHl0aG9uLXNvY2lhbC1hdXRoMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq3g1Cl+3uR5vCnN4HbgjTg+m3nHhteEMyb++ycZYre2bxUfsshER6x33l23tHckRYwm7MdBbrp3LrVoiOCdPblTml1IhEPTCwKMhBKvvWqTvgfcSSnRzAWkLlQYSusayyZK4n9qcYkV5MFni1rbjx+Mr5aOEmb5u33amMKLwSTwIDAQABo4GnMIGkMB0GA1UdDgQWBBRRiBR6zS66fKVokp0yJHbgv3RYmjB1BgNVHSMEbjBsgBRRiBR6zS66fKVokp0yJHbgv3RYmqFJpEcwRTELMAkGA1UEBhMCQ0ExGTAXBgNVBAgTEEJyaXRpc2ggQ29sdW1iaWExGzAZBgNVBAoTEnB5dGhvbi1zb2NpYWwtYXV0aIIJAO7BwdjDZcUWMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAJwsMU3YSaybVjuJ8US0fUhlPOlM40QFCGL4vB3TEbb24Mq8HrjUwrU0JFPGls9a2OYzN2B3e35NorMuxs+grGtr2yP6LvuX+nV6A93wb4ooGHoGfC7VLlyxSSns937SS5R1pzQ4gWzZma2KGWKICWph5zQ0ARVhL63967mGLmoI=",
+ "SOCIAL_AUTH_SAML_SP_PRIVATE_KEY":
"MIICXgIBAAKBgQCq3g1Cl+3uR5vCnN4HbgjTg+m3nHhteEMyb++ycZYre2bxUfsshER6x33l23tHckRYwm7MdBbrp3LrVoiOCdPblTml1IhEPTCwKMhBKvvWqTvgfcSSnRzAWkLlQYSusayyZK4n9qcYkV5MFni1rbjx+Mr5aOEmb5u33amMKLwSTwIDAQABAoGBAIHAg6NJSiYC/NYpVzWfKlasuoNy78R5adXYSNZiCR5V5FNm5OzmODZgXUt6g0A7FomshIT/txQWoV7y5FmwPs8n13JY3Hdt4tJ6MHw2feLo710+OEp9VBQus3JsB2F8ONYrGvs00hPPL7h5av/rzTdE8F67YM1mSgeg7xEF6BghAkEA12OOqSzp2MLTNY7PqOaLDzy4aAMVNN3Ntv2jBN0jq7s1b5ilQ2PGkLwdtkicq/VZcRyUqVbZbMwz05II3nqx3wJBAMsVhRQ5sdFCRBzEbSAm2YEJaFh5u6QT3+zWHMFpPJRnaBAWz3RXKEnleJ+DS2Xz1Jm6ZrmLdZiwMx/8dK5rDZECQQC7GTdWi7ZC3dIcpwaKIGHRhZxmda8ZMkc9Wwwd8H7I8aFUZFPCu0xEc7SXoHHACit8zyfwBYpvMN8gPK3JnOkfAkEAsUSpk0wBMT38one7IZOHzCDgGkq4RbKrhdon45Pus0PIDDM9BrqFimtpbSN4DxhVfZK91DwtfAhhuAvv9cewYQJAPMhpAqv3PBGYmtRDUlWXJQv2JRJJkrvbbqgBed2OX5RRgj5V3SR6PBhLbcTZ+q+1tdPkMFzZo5U6MN5m/6oXvQ==",
+ "SOCIAL_AUTH_SAML_ORG_INFO": {
+ "en-US": {"name": "psa", "displayname": "PSA", "url":
"https://github.com/omab/python-social-auth/"}
+ },
+ "SOCIAL_AUTH_SAML_TECHNICAL_CONTACT":
+ {"givenName": "Tech Gal", "emailAddress": "[email protected]"},
+ "SOCIAL_AUTH_SAML_SUPPORT_CONTACT":
+ {"givenName": "Support Guy", "emailAddress": "[email protected]"},
+ "SOCIAL_AUTH_SAML_ENABLED_IDPS": {
+ "testshib": {
+ "entity_id": "https://idp.testshib.org/idp/shibboleth",
+ "url": "https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO",
+ "x509cert":
"MIIEDjCCAvagAwIBAgIBADANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzEVMBMGA1UECBMMUGVubnN5bHZhbmlhMRMwEQYDVQQHEwpQaXR0c2J1cmdoMREwDwYDVQQKEwhUZXN0U2hpYjEZMBcGA1UEAxMQaWRwLnRlc3RzaGliLm9yZzAeFw0wNjA4MzAyMTEyMjVaFw0xNjA4MjcyMTEyMjVaMGcxCzAJBgNVBAYTAlVTMRUwEwYDVQQIEwxQZW5uc3lsdmFuaWExEzARBgNVBAcTClBpdHRzYnVyZ2gxETAPBgNVBAoTCFRlc3RTaGliMRkwFwYDVQQDExBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArYkCGuTmJp9eAOSGHwRJo1SNatB5ZOKqDM9ysg7CyVTDClcpu93gSP10nH4gkCZOlnESNgttg0r+MqL8tfJC6ybddEFB3YBo8PZajKSe3OQ01Ow3yT4I+Wdg1tsTpSge9gEz7SrC07EkYmHuPtd71CHiUaCWDv+xVfUQX0aTNPFmDixzUjoYzbGDrtAyCqA8f9CN2txIfJnpHE6q6CmKcoLADS4UrNPlhHSzd614kR/JYiks0K4kbRqCQF0Dv0P5Di+rEfefC6glV8ysC8dB5/9nb0yh/ojRuJGmgMWHgWk6h0ihjihqiu4jACovUZ7vVOCgSE5Ipn7OIwqd93zp2wIDAQABo4HEMIHBMB0GA1UdDgQWBBSsBQ869nh83KqZr5jArr4/7b+QazCBkQYDVR0jBIGJMIGGgBSsBQ869nh83KqZr5jArr4/7b+Qa6FrpGkwZzELMAkGA1UEBhMCVVMxFTATBgNVBAgTDFBlbm5zeWx2YW5pYTETMBEGA1UEBxMKUGl0dHNidXJnaDERMA8GA1UEChMIVGVzdFNoaWIxGTAXBgNVBAMTEGlkcC50ZXN0c2hpYi5vcmeCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAjR29PhrCbk8qLN5MFfSVk98t3CT9jHZoYxd8QMRLI4j7iYQxXiGJTT1FXs1nd4Rha9un+LqTfeMMYqISdDDI6tv8iNpkOAvZZUosVkUo93pv1T0RPz35hcHHYq2yee59HJOco2bFlcsH8JBXRSRrJ3Q7Eut+z9uo80JdGNJ4/SJy5UorZ8KazGj16lfJhOBXldgrhppQBb0Nq6HKHguqmwRfJ+WkxemZXzhediAjGeka8nz8JjwxpUjAiSWYKLtJhGEaTqCYxCCX2Dw+dOTqUzHOZ7WKv4JXPK5G/Uhr8K/qhmFT2nIQi538n6rVYLeWj8Bbnl+ev0peYzxFyF5sQA=="
+ },
+ "other": {
+ "entity_id": "https://unused.saml.example.com",
+ "url": "https://unused.saml.example.com/SAML2/Redirect/SSO"
+ }
+ }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/social-auth-core-3.1.0/social_core/tests/backends/test_cognito.py
new/social-auth-core-3.2.0/social_core/tests/backends/test_cognito.py
--- old/social-auth-core-3.1.0/social_core/tests/backends/test_cognito.py
1970-01-01 01:00:00.000000000 +0100
+++ new/social-auth-core-3.2.0/social_core/tests/backends/test_cognito.py
2019-04-21 15:24:23.000000000 +0200
@@ -0,0 +1,36 @@
+import json
+
+from .oauth import OAuth2Test
+
+
+class CognitoAuth2Test(OAuth2Test):
+ backend_path = 'social_core.backends.cognito.CognitoOAuth2'
+ pool_domain = 'https://social_core.auth.eu-west-1.amazoncognito.com'
+ expected_username = 'cognito.account.ABCDE1234'
+ access_token_body = json.dumps({
+ 'access_token': 'foobar',
+ 'token_type': 'bearer'
+ })
+ user_data_body = json.dumps({
+ 'given_name': 'John',
+ 'family_name': 'Doe',
+ 'username': 'cognito.account.ABCDE1234',
+ 'email': '[email protected]',
+ })
+
+ @property
+ def user_data_url(self):
+ return self.backend.user_data_url()
+
+ def extra_settings(self):
+ settings = super(CognitoAuth2Test, self).extra_settings()
+ settings.update({
+ 'SOCIAL_AUTH_' + self.name + '_POOL_DOMAIN': self.pool_domain,
+ })
+ return settings
+
+ 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-3.1.0/social_core/tests/backends/test_linkedin.py
new/social-auth-core-3.2.0/social_core/tests/backends/test_linkedin.py
--- old/social-auth-core-3.1.0/social_core/tests/backends/test_linkedin.py
2018-08-20 15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/tests/backends/test_linkedin.py
2019-04-07 14:33:19.000000000 +0200
@@ -1,23 +1,40 @@
import json
-from six.moves.urllib_parse import urlencode
-
-
-from .oauth import OAuth1Test, OAuth2Test
+from .oauth import OAuth2Test
class BaseLinkedinTest(object):
- user_data_url = 'https://api.linkedin.com/v1/people/~:' \
- '(first-name,id,last-name)'
+ user_data_url = 'https://api.linkedin.com/v2/me' \
+ '?projection=(firstName,id,lastName)'
expected_username = 'FooBar'
access_token_body = json.dumps({
'access_token': 'foobar',
'token_type': 'bearer'
})
+
+ # Reference:
+ # https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self
+ #
-serve/sign-in-with-linkedin?context=linkedin/consumer/context#api-request
user_data_body = json.dumps({
- 'lastName': 'Bar',
- 'id': '1010101010',
- 'firstName': 'Foo'
+ "id": '1010101010',
+ "firstName": {
+ "localized": {
+ "en_US": "Foo"
+ },
+ "preferredLocale": {
+ "country": "US",
+ "language": "en"
+ }
+ },
+ "lastName": {
+ "localized": {
+ "en_US": "Bar"
+ },
+ "preferredLocale": {
+ "country": "US",
+ "language": "en"
+ }
+ }
})
def test_login(self):
@@ -27,15 +44,6 @@
self.do_partial_pipeline()
-class LinkedinOAuth1Test(BaseLinkedinTest, OAuth1Test):
- backend_path = 'social_core.backends.linkedin.LinkedinOAuth'
- request_token_body = urlencode({
- 'oauth_token_secret': 'foobar-secret',
- 'oauth_token': 'foobar',
- 'oauth_callback_confirmed': 'true'
- })
-
-
class LinkedinOAuth2Test(BaseLinkedinTest, OAuth2Test):
backend_path = 'social_core.backends.linkedin.LinkedinOAuth2'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/social-auth-core-3.1.0/social_core/utils.py
new/social-auth-core-3.2.0/social_core/utils.py
--- old/social-auth-core-3.1.0/social_core/utils.py 2018-08-20
15:44:10.000000000 +0200
+++ new/social-auth-core-3.2.0/social_core/utils.py 2019-04-07
15:28:25.000000000 +0200
@@ -4,6 +4,7 @@
import unicodedata
import collections
import functools
+import hmac
import logging
import six
@@ -218,21 +219,12 @@
def constant_time_compare(val1, val2):
- """
- Returns True if the two strings are equal, False otherwise.
- The time taken is independent of the number of characters that match.
- This code was borrowed from Django 1.5.4-final
- """
- if len(val1) != len(val2):
- return False
- result = 0
- if six.PY3 and isinstance(val1, bytes) and isinstance(val2, bytes):
- for x, y in zip(val1, val2):
- result |= x ^ y
- else:
- for x, y in zip(val1, val2):
- result |= ord(x) ^ ord(y)
- return result == 0
+ """Compare two values and prevent timing attacks for cryptographic use."""
+ if isinstance(val1, six.text_type):
+ val1 = val1.encode('utf-8')
+ if isinstance(val2, six.text_type):
+ val2 = val2.encode('utf-8')
+ return hmac.compare_digest(val1, val2)
def is_url(value):