Merge tag 'upstream/3.1.0' into debian/master
W. Martin Borgert
5 years ago
0 | *.py[cod] | |
1 | ||
2 | # C extensions | |
3 | *.so | |
4 | ||
5 | # Packages | |
6 | *.egg | |
7 | *.egg-info | |
8 | dist | |
9 | build | |
10 | eggs | |
11 | parts | |
12 | bin | |
13 | var | |
14 | sdist | |
15 | develop-eggs | |
16 | .installed.cfg | |
17 | lib | |
18 | lib64 | |
19 | ||
20 | # Installer logs | |
21 | pip-log.txt | |
22 | ||
23 | # Unit test / coverage reports | |
24 | .coverage | |
25 | .tox | |
26 | nosetests.xml | |
27 | ||
28 | # Translations | |
29 | *.mo | |
30 | ||
31 | # Mr Developer | |
32 | .mr.developer.cfg | |
33 | .project | |
34 | .pydevproject | |
35 | ||
36 | # PyCharm | |
37 | .idea/ | |
38 | ||
39 | test.db | |
40 | local_settings.py | |
41 | sessions/ | |
42 | _build/ | |
43 | fabfile.py | |
44 | changelog.sh | |
45 | ||
46 | .DS_Store | |
47 | .\#* | |
48 | \#*\# | |
49 | ||
50 | .python-version |
0 | language: python | |
1 | sudo: false | |
2 | matrix: | |
3 | include: | |
4 | - python: 2.7 | |
5 | env: TOXENV=py27 | |
6 | - python: 3.4 | |
7 | env: TOXENV=py34 | |
8 | - python: 3.5 | |
9 | env: TOXENV=py35 | |
10 | - python: pypy | |
11 | env: TOXENV=pypy | |
12 | - python: 3.6 | |
13 | env: TOXENV=py36 | |
14 | fast_finish: true | |
15 | addons: | |
16 | apt: | |
17 | packages: | |
18 | - libxmlsec1-dev | |
19 | - swig | |
20 | install: | |
21 | - pip install tox -U pip | |
22 | script: | |
23 | - tox -e $TOXENV |
5 | 5 | and this project adheres to [Semantic Versioning](http://semver.org/). |
6 | 6 | |
7 | 7 | ## [Unreleased](https://github.com/python-social-auth/social-core/commits/master) |
8 | ||
9 | ## [3.1.0](https://github.com/python-social-auth/social-core/releases/tag/3.1.0) - 2019-02-20 | |
10 | ||
11 | ### Added | |
12 | - Universe Ticketing backend | |
13 | - Auth0.com authentication backend | |
14 | ||
15 | ### Changed | |
16 | - Update Bungie backend dropping any Django reference | |
17 | - Enable and fix JWT related tests | |
18 | - Remove PyPy support from Tox | |
19 | - Drop support for Python 3.4 in Tox | |
20 | - Allow to override JWT decode options in Open ID Connect base backend | |
21 | - Pass access token via Authorization header to Google user data url | |
22 | - Updated `user_data` method in `AzureADOAuth2` to return `access_token` if | |
23 | `id_token` is not present in response | |
8 | 24 | |
9 | 25 | ## [3.0.0](https://github.com/python-social-auth/social-core/releases/tag/3.0.0) - 2019-01-14 |
10 | 26 |
0 | # How to contribute | |
1 | ||
2 | I like to encourage you to contribute to the repository. | |
3 | ||
4 | This should be as easy as possible for you but there are a few things | |
5 | to consider when contributing. The following guidelines for | |
6 | contribution should be followed if you want to submit a pull request. | |
7 | ||
8 | ## How to prepare | |
9 | ||
10 | * You need a [GitHub account](https://github.com/signup/free) | |
11 | * Submit an [issue ticket](https://github.com/python-social-auth/social-core/issues) | |
12 | for your issue if there is no one yet. | |
13 | * Describe the issue and include steps to reproduce if it's a bug. | |
14 | * Ensure to mention the earliest version that you know is affected. | |
15 | * If you are able and want to fix this, fork the repository on GitHub | |
16 | ||
17 | ## Make Changes | |
18 | ||
19 | * In your forked repository, create a topic branch for your upcoming | |
20 | patch. (e.g. `feature/new-backend` or `bug/auth-fails`) | |
21 | * Usually this is based on the `master` branch. | |
22 | * Create a branch based on master `git branch bug/auth-fails master` | |
23 | then checkout the new branch with `git checkout bug/auth-fails`. | |
24 | Please avoid working directly on the `master` branch. | |
25 | * Make commits of logical units and describe them properly. | |
26 | * Make sure you stick to [PEP8](https://www.python.org/dev/peps/pep-0008/) | |
27 | coding style that is used already. | |
28 | * If possible, submit tests to your patch / new feature so it can be tested easily. | |
29 | * Assure nothing is broken by running all the tests. | |
30 | * Add a meaningful entry to the `CHANGELOG.md` document. | |
31 | ||
32 | ## Submit Changes | |
33 | ||
34 | * Push your changes to a topic branch in your fork of the repository. | |
35 | * Open a pull request to the original repository and choose the right | |
36 | original branch you want to patch. | |
37 | * If not done in commit messages (which you really should do) please | |
38 | reference and update your issue with the code changes. But _please | |
39 | do not close the issue yourself_. | |
40 | * Even if you have write access to the repository, do not directly | |
41 | push or merge pull-requests. Let another team member review your | |
42 | pull request and approve. | |
43 | ||
44 | # Additional Resources | |
45 | ||
46 | * [General GitHub documentation](http://help.github.com/) | |
47 | * [GitHub pull request documentation](http://help.github.com/send-pull-requests/) | |
48 | * [Read the Issue Guidelines by @necolas](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md) | |
49 | for more details | |
50 | ||
51 | # Notes | |
52 | ||
53 | This documented is based in the work from [anselmh/CONTRIBUTING.md](https://github.com/anselmh/CONTRIBUTING.md), | |
54 | licensed as [Creative Commons Attribution 3.0 Unported License](https://github.com/anselmh/CONTRIBUTING.md/blob/master/README.md#license). |
0 | FROM omab/pyenv-tox | |
1 | MAINTAINER Matías Aguirre <matiasaguirre@gmail.com> | |
2 | RUN apt-get update | |
3 | RUN apt-get install -y make libxml2-dev libxmlsec1-dev pkg-config |
0 | PYTHON_VERSIONS := 2.7.12 3.4.4 3.5.2 pypy-4.0.1 | |
1 | ||
2 | build: | |
3 | @ BUILD_VERSION=2 python setup.py sdist | |
4 | @ BUILD_VERSION=2 python setup.py bdist_wheel --python-tag py2 | |
5 | @ BUILD_VERSION=3 python setup.py bdist_wheel --python-tag py3 | |
6 | ||
7 | publish: | |
8 | @ BUILD_VERSION=2 python setup.py sdist upload | |
9 | @ BUILD_VERSION=2 python setup.py bdist_wheel --python-tag py2 upload | |
10 | @ BUILD_VERSION=3 python setup.py bdist_wheel --python-tag py3 upload | |
11 | ||
12 | check-pyenv: | |
13 | @ which pyenv | |
14 | ||
15 | # Dependencies: libxml2-dev libxmlsec1-dev libbz2-dev libsqlite3-dev | |
16 | # libreadline-dev zlib1g-dev libncurses5-dev libssl-dev | |
17 | # libgdbm-dev libncursesw5-dev xz-utils swig build-essential | |
18 | setup-pyenv-python: | |
19 | @ pyenv install -s $(version) | |
20 | @ pyenv local $(version) | |
21 | @ pip install --upgrade setuptools pip tox | |
22 | @ pyenv local --unset | |
23 | ||
24 | setup-pyenv: check-pyenv | |
25 | @ eval "$(pyenv init -)" | |
26 | @ $(foreach version, \ | |
27 | $(PYTHON_VERSIONS), \ | |
28 | ${MAKE} setup-pyenv-python version=$(version);) | |
29 | @ pyenv local $(PYTHON_VERSIONS) | |
30 | ||
31 | run-tox: | |
32 | @ tox | |
33 | ||
34 | docker-tox-build: | |
35 | @ docker inspect omab/psa-social-core >/dev/null 2>&1 || ( \ | |
36 | docker build -t omab/psa-social-core . \ | |
37 | ) | |
38 | ||
39 | docker-tox: docker-tox-build | |
40 | @ docker run -it --rm \ | |
41 | --name psa-social-core-test \ | |
42 | -v "`pwd`:/code" \ | |
43 | -w /code omab/psa-social-core tox | |
44 | ||
45 | docker-bash: docker-tox-build | |
46 | @ docker run -it --rm \ | |
47 | --name psa-social-core-test \ | |
48 | -v "`pwd`:/code" \ | |
49 | -w /code omab/psa-social-core bash | |
50 | ||
51 | tests: setup-pyenv run-tox clean | |
52 | ||
53 | clean: | |
54 | @ find . -name '*.py[co]' -delete | |
55 | @ find . -name '__pycache__' -delete | |
56 | @ rm -rf *.egg-info dist build |
0 | Metadata-Version: 2.1 | |
1 | Name: social-auth-core | |
2 | Version: 3.1.0 | |
3 | Summary: Python social authentication made simple. | |
4 | Home-page: https://github.com/python-social-auth/social-core | |
5 | Author: Matias Aguirre | |
6 | Author-email: matiasaguirre@gmail.com | |
7 | License: BSD | |
8 | Description: # Python Social Auth - Core | |
9 | ||
10 | [![Build Status](https://travis-ci.org/python-social-auth/social-core.svg?branch=master)](https://travis-ci.org/python-social-auth/social-core) | |
11 | [![Donate](https://img.shields.io/badge/Donate-PayPal-orange.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=matiasaguirre%40gmail%2ecom&lc=US&item_name=Python%20Social%20Auth&no_note=0¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest) | |
12 | ||
13 | Python Social Auth is an easy to setup social authentication/registration | |
14 | mechanism with support for several frameworks and auth providers. | |
15 | ||
16 | ## Description | |
17 | ||
18 | This is the core component of the python-social-auth ecosystem, it | |
19 | implements the common interface to define new authentication backends | |
20 | to third parties services, implement integrations with web frameworks | |
21 | and storage solutions. | |
22 | ||
23 | ## Documentation | |
24 | ||
25 | Project documentation is available at http://python-social-auth.readthedocs.org/. | |
26 | ||
27 | ## Setup | |
28 | ||
29 | ```shell | |
30 | $ pip install social-auth-core | |
31 | ``` | |
32 | ||
33 | ## Contributing | |
34 | ||
35 | See the [CONTRIBUTING.md](CONTRIBUTING.md) document for details. | |
36 | ||
37 | ## Versioning | |
38 | ||
39 | This project follows [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html). | |
40 | ||
41 | ## License | |
42 | ||
43 | This project follows the BSD license. See the [LICENSE](LICENSE) for details. | |
44 | ||
45 | ## Donations | |
46 | ||
47 | This project is maintened on my spare time, consider donating to keep | |
48 | it improving. | |
49 | ||
50 | [![Donate](https://img.shields.io/badge/Donate-PayPal-orange.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=matiasaguirre%40gmail%2ecom&lc=US&item_name=Python%20Social%20Auth&no_note=0¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest) | |
51 | ||
52 | Keywords: openid,oauth,saml,social auth | |
53 | Platform: UNKNOWN | |
54 | Classifier: Development Status :: 4 - Beta | |
55 | Classifier: Topic :: Internet | |
56 | Classifier: License :: OSI Approved :: BSD License | |
57 | Classifier: Intended Audience :: Developers | |
58 | Classifier: Environment :: Web Environment | |
59 | Classifier: Programming Language :: Python | |
60 | Classifier: Programming Language :: Python :: 2.7 | |
61 | Classifier: Programming Language :: Python :: 3 | |
62 | Provides-Extra: openidconnect | |
63 | Provides-Extra: saml | |
64 | Provides-Extra: allpy2 | |
65 | Provides-Extra: azuread | |
66 | Provides-Extra: allpy3 | |
67 | Provides-Extra: all |
0 | 0 | [flake8] |
1 | 1 | max-line-length = 119 |
2 | # Ignore some well known paths | |
3 | 2 | exclude = .venv,.tox,dist,doc,build,*.egg,db/env.py,db/versions/*.py,site |
4 | 3 | |
5 | 4 | [nosetests] |
6 | verbosity=2 | |
7 | with-coverage=1 | |
8 | cover-erase=1 | |
9 | cover-package=social_core | |
10 | rednose=1 | |
11 | where=social_core/tests | |
5 | verbosity = 2 | |
6 | with-coverage = 1 | |
7 | cover-erase = 1 | |
8 | cover-package = social_core | |
9 | rednose = 1 | |
10 | where = social_core/tests | |
11 | ||
12 | [egg_info] | |
13 | tag_build = | |
14 | tag_date = 0 | |
15 |
87 | 87 | 'saml': [requirements_saml], |
88 | 88 | 'azuread': [requirements_azuread], |
89 | 89 | 'all': [requirements_all], |
90 | 'allpy2': [requirements_all, requirements_py2], | |
91 | 'allpy3': [requirements_all, requirements_py3], | |
90 | 92 | ':python_version < "3.0"': [requirements_py2], |
91 | 93 | ':python_version >= "3.0"': [requirements_py3], |
92 | 94 | }, |
0 | Metadata-Version: 2.1 | |
1 | Name: social-auth-core | |
2 | Version: 3.1.0 | |
3 | Summary: Python social authentication made simple. | |
4 | Home-page: https://github.com/python-social-auth/social-core | |
5 | Author: Matias Aguirre | |
6 | Author-email: matiasaguirre@gmail.com | |
7 | License: BSD | |
8 | Description: # Python Social Auth - Core | |
9 | ||
10 | [![Build Status](https://travis-ci.org/python-social-auth/social-core.svg?branch=master)](https://travis-ci.org/python-social-auth/social-core) | |
11 | [![Donate](https://img.shields.io/badge/Donate-PayPal-orange.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=matiasaguirre%40gmail%2ecom&lc=US&item_name=Python%20Social%20Auth&no_note=0¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest) | |
12 | ||
13 | Python Social Auth is an easy to setup social authentication/registration | |
14 | mechanism with support for several frameworks and auth providers. | |
15 | ||
16 | ## Description | |
17 | ||
18 | This is the core component of the python-social-auth ecosystem, it | |
19 | implements the common interface to define new authentication backends | |
20 | to third parties services, implement integrations with web frameworks | |
21 | and storage solutions. | |
22 | ||
23 | ## Documentation | |
24 | ||
25 | Project documentation is available at http://python-social-auth.readthedocs.org/. | |
26 | ||
27 | ## Setup | |
28 | ||
29 | ```shell | |
30 | $ pip install social-auth-core | |
31 | ``` | |
32 | ||
33 | ## Contributing | |
34 | ||
35 | See the [CONTRIBUTING.md](CONTRIBUTING.md) document for details. | |
36 | ||
37 | ## Versioning | |
38 | ||
39 | This project follows [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html). | |
40 | ||
41 | ## License | |
42 | ||
43 | This project follows the BSD license. See the [LICENSE](LICENSE) for details. | |
44 | ||
45 | ## Donations | |
46 | ||
47 | This project is maintened on my spare time, consider donating to keep | |
48 | it improving. | |
49 | ||
50 | [![Donate](https://img.shields.io/badge/Donate-PayPal-orange.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=matiasaguirre%40gmail%2ecom&lc=US&item_name=Python%20Social%20Auth&no_note=0¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHostedGuest) | |
51 | ||
52 | Keywords: openid,oauth,saml,social auth | |
53 | Platform: UNKNOWN | |
54 | Classifier: Development Status :: 4 - Beta | |
55 | Classifier: Topic :: Internet | |
56 | Classifier: License :: OSI Approved :: BSD License | |
57 | Classifier: Intended Audience :: Developers | |
58 | Classifier: Environment :: Web Environment | |
59 | Classifier: Programming Language :: Python | |
60 | Classifier: Programming Language :: Python :: 2.7 | |
61 | Classifier: Programming Language :: Python :: 3 | |
62 | Provides-Extra: openidconnect | |
63 | Provides-Extra: saml | |
64 | Provides-Extra: allpy2 | |
65 | Provides-Extra: azuread | |
66 | Provides-Extra: allpy3 | |
67 | Provides-Extra: all |
0 | CHANGELOG.md | |
1 | LICENSE | |
2 | MANIFEST.in | |
3 | README.md | |
4 | requirements-azuread.txt | |
5 | requirements-base.txt | |
6 | requirements-openidconnect.txt | |
7 | requirements-python2.txt | |
8 | requirements-python3.txt | |
9 | requirements-saml-python2.txt | |
10 | requirements-saml-python3.txt | |
11 | setup.cfg | |
12 | setup.py | |
13 | social_auth_core.egg-info/PKG-INFO | |
14 | social_auth_core.egg-info/SOURCES.txt | |
15 | social_auth_core.egg-info/dependency_links.txt | |
16 | social_auth_core.egg-info/not-zip-safe | |
17 | social_auth_core.egg-info/requires.txt | |
18 | social_auth_core.egg-info/top_level.txt | |
19 | social_core/__init__.py | |
20 | social_core/actions.py | |
21 | social_core/exceptions.py | |
22 | social_core/storage.py | |
23 | social_core/store.py | |
24 | social_core/strategy.py | |
25 | social_core/utils.py | |
26 | social_core/backends/__init__.py | |
27 | social_core/backends/amazon.py | |
28 | social_core/backends/angel.py | |
29 | social_core/backends/aol.py | |
30 | social_core/backends/appsfuel.py | |
31 | social_core/backends/arcgis.py | |
32 | social_core/backends/asana.py | |
33 | social_core/backends/atlassian.py | |
34 | social_core/backends/auth0.py | |
35 | social_core/backends/azuread.py | |
36 | social_core/backends/azuread_b2c.py | |
37 | social_core/backends/azuread_tenant.py | |
38 | social_core/backends/base.py | |
39 | social_core/backends/battlenet.py | |
40 | social_core/backends/beats.py | |
41 | social_core/backends/behance.py | |
42 | social_core/backends/belgiumeid.py | |
43 | social_core/backends/bitbucket.py | |
44 | social_core/backends/box.py | |
45 | social_core/backends/bungie.py | |
46 | social_core/backends/changetip.py | |
47 | social_core/backends/chatwork.py | |
48 | social_core/backends/classlink.py | |
49 | social_core/backends/clef.py | |
50 | social_core/backends/coding.py | |
51 | social_core/backends/coinbase.py | |
52 | social_core/backends/coursera.py | |
53 | social_core/backends/dailymotion.py | |
54 | social_core/backends/deezer.py | |
55 | social_core/backends/digitalocean.py | |
56 | social_core/backends/discord.py | |
57 | social_core/backends/disqus.py | |
58 | social_core/backends/docker.py | |
59 | social_core/backends/douban.py | |
60 | social_core/backends/dribbble.py | |
61 | social_core/backends/drip.py | |
62 | social_core/backends/dropbox.py | |
63 | social_core/backends/echosign.py | |
64 | social_core/backends/edmodo.py | |
65 | social_core/backends/elixir.py | |
66 | social_core/backends/email.py | |
67 | social_core/backends/eventbrite.py | |
68 | social_core/backends/eveonline.py | |
69 | social_core/backends/evernote.py | |
70 | social_core/backends/exacttarget.py | |
71 | social_core/backends/facebook.py | |
72 | social_core/backends/fedora.py | |
73 | social_core/backends/fitbit.py | |
74 | social_core/backends/five_hundred_px.py | |
75 | social_core/backends/flat.py | |
76 | social_core/backends/flickr.py | |
77 | social_core/backends/foursquare.py | |
78 | social_core/backends/gae.py | |
79 | social_core/backends/github.py | |
80 | social_core/backends/github_enterprise.py | |
81 | social_core/backends/gitlab.py | |
82 | social_core/backends/globus.py | |
83 | social_core/backends/goclio.py | |
84 | social_core/backends/goclioeu.py | |
85 | social_core/backends/google.py | |
86 | social_core/backends/google_openidconnect.py | |
87 | social_core/backends/instagram.py | |
88 | social_core/backends/itembase.py | |
89 | social_core/backends/jawbone.py | |
90 | social_core/backends/justgiving.py | |
91 | social_core/backends/kakao.py | |
92 | social_core/backends/keycloak.py | |
93 | social_core/backends/khanacademy.py | |
94 | social_core/backends/lastfm.py | |
95 | social_core/backends/launchpad.py | |
96 | social_core/backends/legacy.py | |
97 | social_core/backends/line.py | |
98 | social_core/backends/linkedin.py | |
99 | social_core/backends/live.py | |
100 | social_core/backends/livejournal.py | |
101 | social_core/backends/loginradius.py | |
102 | social_core/backends/lyft.py | |
103 | social_core/backends/mailchimp.py | |
104 | social_core/backends/mailru.py | |
105 | social_core/backends/mapmyfitness.py | |
106 | social_core/backends/mediawiki.py | |
107 | social_core/backends/meetup.py | |
108 | social_core/backends/mendeley.py | |
109 | social_core/backends/microsoft.py | |
110 | social_core/backends/mineid.py | |
111 | social_core/backends/mixcloud.py | |
112 | social_core/backends/monzo.py | |
113 | social_core/backends/moves.py | |
114 | social_core/backends/nationbuilder.py | |
115 | social_core/backends/naver.py | |
116 | social_core/backends/ngpvan.py | |
117 | social_core/backends/nk.py | |
118 | social_core/backends/oauth.py | |
119 | social_core/backends/odnoklassniki.py | |
120 | social_core/backends/open_id.py | |
121 | social_core/backends/open_id_connect.py | |
122 | social_core/backends/openshift.py | |
123 | social_core/backends/openstreetmap.py | |
124 | social_core/backends/orbi.py | |
125 | social_core/backends/orcid.py | |
126 | social_core/backends/patreon.py | |
127 | social_core/backends/persona.py | |
128 | social_core/backends/phabricator.py | |
129 | social_core/backends/pinterest.py | |
130 | social_core/backends/pixelpin.py | |
131 | social_core/backends/pocket.py | |
132 | social_core/backends/podio.py | |
133 | social_core/backends/professionali.py | |
134 | social_core/backends/pushbullet.py | |
135 | social_core/backends/qiita.py | |
136 | social_core/backends/qq.py | |
137 | social_core/backends/quizlet.py | |
138 | social_core/backends/rdio.py | |
139 | social_core/backends/readability.py | |
140 | social_core/backends/reddit.py | |
141 | social_core/backends/runkeeper.py | |
142 | social_core/backends/salesforce.py | |
143 | social_core/backends/saml.py | |
144 | social_core/backends/scistarter.py | |
145 | social_core/backends/shimmering.py | |
146 | social_core/backends/shopify.py | |
147 | social_core/backends/sketchfab.py | |
148 | social_core/backends/skyrock.py | |
149 | social_core/backends/slack.py | |
150 | social_core/backends/soundcloud.py | |
151 | social_core/backends/spotify.py | |
152 | social_core/backends/stackoverflow.py | |
153 | social_core/backends/steam.py | |
154 | social_core/backends/stocktwits.py | |
155 | social_core/backends/strava.py | |
156 | social_core/backends/stripe.py | |
157 | social_core/backends/suse.py | |
158 | social_core/backends/taobao.py | |
159 | social_core/backends/telegram.py | |
160 | social_core/backends/thisismyjam.py | |
161 | social_core/backends/trello.py | |
162 | social_core/backends/tripit.py | |
163 | social_core/backends/tumblr.py | |
164 | social_core/backends/twilio.py | |
165 | social_core/backends/twitch.py | |
166 | social_core/backends/twitter.py | |
167 | social_core/backends/uber.py | |
168 | social_core/backends/ubuntu.py | |
169 | social_core/backends/udata.py | |
170 | social_core/backends/universe.py | |
171 | social_core/backends/untappd.py | |
172 | social_core/backends/upwork.py | |
173 | social_core/backends/username.py | |
174 | social_core/backends/utils.py | |
175 | social_core/backends/vend.py | |
176 | social_core/backends/vimeo.py | |
177 | social_core/backends/vk.py | |
178 | social_core/backends/weibo.py | |
179 | social_core/backends/weixin.py | |
180 | social_core/backends/withings.py | |
181 | social_core/backends/wunderlist.py | |
182 | social_core/backends/xing.py | |
183 | social_core/backends/yahoo.py | |
184 | social_core/backends/yammer.py | |
185 | social_core/backends/yandex.py | |
186 | social_core/backends/zotero.py | |
187 | social_core/pipeline/__init__.py | |
188 | social_core/pipeline/debug.py | |
189 | social_core/pipeline/disconnect.py | |
190 | social_core/pipeline/mail.py | |
191 | social_core/pipeline/partial.py | |
192 | social_core/pipeline/social_auth.py | |
193 | social_core/pipeline/user.py | |
194 | social_core/pipeline/utils.py | |
195 | social_core/tests/__init__.py | |
196 | social_core/tests/models.py | |
197 | social_core/tests/pipeline.py | |
198 | social_core/tests/requirements-base.txt | |
199 | social_core/tests/requirements-pypy.txt | |
200 | social_core/tests/requirements-python2.txt | |
201 | social_core/tests/requirements-python3.txt | |
202 | social_core/tests/requirements.txt | |
203 | social_core/tests/strategy.py | |
204 | social_core/tests/test_exceptions.py | |
205 | social_core/tests/test_partial.py | |
206 | social_core/tests/test_pipeline.py | |
207 | social_core/tests/test_storage.py | |
208 | social_core/tests/test_utils.py | |
209 | social_core/tests/testkey.pem | |
210 | social_core/tests/actions/__init__.py | |
211 | social_core/tests/actions/actions.py | |
212 | social_core/tests/actions/test_associate.py | |
213 | social_core/tests/actions/test_disconnect.py | |
214 | social_core/tests/actions/test_login.py | |
215 | social_core/tests/backends/__init__.py | |
216 | social_core/tests/backends/base.py | |
217 | social_core/tests/backends/legacy.py | |
218 | social_core/tests/backends/oauth.py | |
219 | social_core/tests/backends/open_id.py | |
220 | social_core/tests/backends/open_id_connect.py | |
221 | social_core/tests/backends/test_amazon.py | |
222 | social_core/tests/backends/test_angel.py | |
223 | social_core/tests/backends/test_arcgis.py | |
224 | social_core/tests/backends/test_asana.py | |
225 | social_core/tests/backends/test_atlassian.py | |
226 | social_core/tests/backends/test_auth0.py | |
227 | social_core/tests/backends/test_azuread.py | |
228 | social_core/tests/backends/test_azuread_b2c.py | |
229 | social_core/tests/backends/test_behance.py | |
230 | social_core/tests/backends/test_bitbucket.py | |
231 | social_core/tests/backends/test_box.py | |
232 | social_core/tests/backends/test_broken.py | |
233 | social_core/tests/backends/test_chatwork.py | |
234 | social_core/tests/backends/test_clef.py | |
235 | social_core/tests/backends/test_coinbase.py | |
236 | social_core/tests/backends/test_coursera.py | |
237 | social_core/tests/backends/test_dailymotion.py | |
238 | social_core/tests/backends/test_deezer.py | |
239 | social_core/tests/backends/test_digitalocean.py | |
240 | social_core/tests/backends/test_disqus.py | |
241 | social_core/tests/backends/test_dribbble.py | |
242 | social_core/tests/backends/test_drip.py | |
243 | social_core/tests/backends/test_dropbox.py | |
244 | social_core/tests/backends/test_dummy.py | |
245 | social_core/tests/backends/test_edmodo.py | |
246 | social_core/tests/backends/test_elixir.py | |
247 | social_core/tests/backends/test_email.py | |
248 | social_core/tests/backends/test_eventbrite.py | |
249 | social_core/tests/backends/test_evernote.py | |
250 | social_core/tests/backends/test_facebook.py | |
251 | social_core/tests/backends/test_fitbit.py | |
252 | social_core/tests/backends/test_five_hundred_px.py | |
253 | social_core/tests/backends/test_flat.py | |
254 | social_core/tests/backends/test_flickr.py | |
255 | social_core/tests/backends/test_foursquare.py | |
256 | social_core/tests/backends/test_github.py | |
257 | social_core/tests/backends/test_github_enterprise.py | |
258 | social_core/tests/backends/test_gitlab.py | |
259 | social_core/tests/backends/test_globus.py | |
260 | social_core/tests/backends/test_google.py | |
261 | social_core/tests/backends/test_instagram.py | |
262 | social_core/tests/backends/test_itembase.py | |
263 | social_core/tests/backends/test_kakao.py | |
264 | social_core/tests/backends/test_keycloak.py | |
265 | social_core/tests/backends/test_khanacademy.py | |
266 | social_core/tests/backends/test_linkedin.py | |
267 | social_core/tests/backends/test_live.py | |
268 | social_core/tests/backends/test_livejournal.py | |
269 | social_core/tests/backends/test_lyft.py | |
270 | social_core/tests/backends/test_mapmyfitness.py | |
271 | social_core/tests/backends/test_mineid.py | |
272 | social_core/tests/backends/test_mixcloud.py | |
273 | social_core/tests/backends/test_nationbuilder.py | |
274 | social_core/tests/backends/test_naver.py | |
275 | social_core/tests/backends/test_ngpvan.py | |
276 | social_core/tests/backends/test_orbi.py | |
277 | social_core/tests/backends/test_patreon.py | |
278 | social_core/tests/backends/test_phabricator.py | |
279 | social_core/tests/backends/test_pinterest.py | |
280 | social_core/tests/backends/test_podio.py | |
281 | social_core/tests/backends/test_qiita.py | |
282 | social_core/tests/backends/test_quizlet.py | |
283 | social_core/tests/backends/test_readability.py | |
284 | social_core/tests/backends/test_reddit.py | |
285 | social_core/tests/backends/test_saml.py | |
286 | social_core/tests/backends/test_scistarter.py | |
287 | social_core/tests/backends/test_sketchfab.py | |
288 | social_core/tests/backends/test_skyrock.py | |
289 | social_core/tests/backends/test_slack.py | |
290 | social_core/tests/backends/test_soundcloud.py | |
291 | social_core/tests/backends/test_spotify.py | |
292 | social_core/tests/backends/test_stackoverflow.py | |
293 | social_core/tests/backends/test_steam.py | |
294 | social_core/tests/backends/test_stocktwits.py | |
295 | social_core/tests/backends/test_strava.py | |
296 | social_core/tests/backends/test_stripe.py | |
297 | social_core/tests/backends/test_taobao.py | |
298 | social_core/tests/backends/test_thisismyjam.py | |
299 | social_core/tests/backends/test_tripit.py | |
300 | social_core/tests/backends/test_tumblr.py | |
301 | social_core/tests/backends/test_twitch.py | |
302 | social_core/tests/backends/test_twitter.py | |
303 | social_core/tests/backends/test_uber.py | |
304 | social_core/tests/backends/test_udata.py | |
305 | social_core/tests/backends/test_universe.py | |
306 | social_core/tests/backends/test_upwork.py | |
307 | social_core/tests/backends/test_username.py | |
308 | social_core/tests/backends/test_utils.py | |
309 | social_core/tests/backends/test_vk.py | |
310 | social_core/tests/backends/test_wunderlist.py | |
311 | social_core/tests/backends/test_xing.py | |
312 | social_core/tests/backends/test_yahoo.py | |
313 | social_core/tests/backends/test_yammer.py | |
314 | social_core/tests/backends/test_yandex.py | |
315 | social_core/tests/backends/test_zotero.py | |
316 | social_core/tests/backends/data/saml_response.txt⏎ |
0 | requests>=2.9.1 | |
1 | oauthlib>=1.0.3 | |
2 | requests-oauthlib>=0.6.1 | |
3 | six>=1.10.0 | |
4 | PyJWT>=1.4.0 | |
5 | ||
6 | [:python_version < "3.0"] | |
7 | python-openid>=2.2.5 | |
8 | ||
9 | [:python_version >= "3.0"] | |
10 | defusedxml>=0.5.0rc1 | |
11 | python3-openid>=3.0.10 | |
12 | ||
13 | [all] | |
14 | python-jose>=3.0.0 | |
15 | pyjwt>=1.7.1 | |
16 | python-saml>=2.2.0 | |
17 | cryptography>=2.1.1 | |
18 | ||
19 | [allpy2] | |
20 | python-jose>=3.0.0 | |
21 | pyjwt>=1.7.1 | |
22 | python-saml>=2.2.0 | |
23 | cryptography>=2.1.1 | |
24 | python-openid>=2.2.5 | |
25 | ||
26 | [allpy3] | |
27 | python-jose>=3.0.0 | |
28 | pyjwt>=1.7.1 | |
29 | python-saml>=2.2.0 | |
30 | cryptography>=2.1.1 | |
31 | defusedxml>=0.5.0rc1 | |
32 | python3-openid>=3.0.10 | |
33 | ||
34 | [azuread] | |
35 | cryptography>=2.1.1 | |
36 | ||
37 | [openidconnect] | |
38 | python-jose>=3.0.0 | |
39 | pyjwt>=1.7.1 | |
40 | ||
41 | [saml] | |
42 | python-saml>=2.2.0 |
0 | social_core |
0 | """ | |
1 | Auth0 implementation based on: | |
2 | https://auth0.com/docs/quickstart/webapp/django/01-login | |
3 | """ | |
4 | from jose import jwt | |
5 | ||
6 | from .oauth import BaseOAuth2 | |
7 | ||
8 | ||
9 | class Auth0OAuth2(BaseOAuth2): | |
10 | """Auth0 OAuth authentication backend""" | |
11 | name = 'auth0' | |
12 | SCOPE_SEPARATOR = ' ' | |
13 | ACCESS_TOKEN_METHOD = 'POST' | |
14 | EXTRA_DATA = [ | |
15 | ('picture', 'picture') | |
16 | ] | |
17 | ||
18 | def api_path(self, path=''): | |
19 | """Build API path for Auth0 domain""" | |
20 | return 'https://{domain}/{path}'.format(domain=self.setting('DOMAIN'), | |
21 | path=path) | |
22 | ||
23 | def authorization_url(self): | |
24 | return self.api_path('authorize') | |
25 | ||
26 | def access_token_url(self): | |
27 | return self.api_path('oauth/token') | |
28 | ||
29 | def get_user_id(self, details, response): | |
30 | """Return current user id.""" | |
31 | return details['user_id'] | |
32 | ||
33 | def get_user_details(self, response): | |
34 | # Obtain JWT and the keys to validate the signature | |
35 | id_token = response.get('id_token') | |
36 | jwks = self.get_json(self.api_path('.well-known/jwks.json')) | |
37 | issuer = self.api_path() | |
38 | audience = self.setting('KEY') # CLIENT_ID | |
39 | payload = jwt.decode(id_token, | |
40 | jwks, | |
41 | algorithms=['RS256'], | |
42 | audience=audience, | |
43 | issuer=issuer) | |
44 | fullname, first_name, last_name = self.get_user_names(payload['name']) | |
45 | return {'username': payload['nickname'], | |
46 | 'email': payload['email'], | |
47 | 'fullname': fullname, | |
48 | 'first_name': first_name, | |
49 | 'last_name': last_name, | |
50 | 'picture': payload['picture'], | |
51 | 'user_id': payload['sub']} |
76 | 76 | |
77 | 77 | def user_data(self, access_token, *args, **kwargs): |
78 | 78 | response = kwargs.get('response') |
79 | id_token = response.get('id_token') | |
79 | if response and response.get('id_token'): | |
80 | id_token = response.get('id_token') | |
81 | else: | |
82 | id_token = access_token | |
83 | ||
80 | 84 | try: |
81 | 85 | decoded_id_token = jwt_decode(id_token, verify=False) |
82 | 86 | except (DecodeError, ExpiredSignature) as de: |
0 | 0 | """ |
1 | 1 | Bungie OAuth2 backend |
2 | 2 | """ |
3 | import requests | |
4 | ||
3 | 5 | from social_core.backends.oauth import BaseOAuth2 |
4 | from django.conf import settings | |
5 | 6 | |
6 | 7 | |
7 | 8 | class BungieOAuth2(BaseOAuth2): |
8 | ||
9 | 9 | name = 'bungie' |
10 | 10 | ID_KEY = 'membership_id' |
11 | 11 | AUTHORIZATION_URL = 'https://www.bungie.net/en/oauth/authorize/' |
27 | 27 | |
28 | 28 | def auth_headers(self): |
29 | 29 | """Adds X-API-KEY and Origin""" |
30 | return {'X-API-KEY': settings.SOCIAL_AUTH_BUNGIE_API_KEY, | |
31 | 'Content-Type': 'application/x-www-form-urlencoded', | |
32 | 'Origin': settings.SOCIAL_AUTH_BUNGIE_ORIGIN, | |
33 | 'Accept': 'application/json' | |
34 | } | |
30 | return { | |
31 | 'X-API-KEY': self.setting('API_KEY'), | |
32 | 'Content-Type': 'application/x-www-form-urlencoded', | |
33 | 'Origin': self.setting('ORIGIN'), | |
34 | 'Accept': 'application/json' | |
35 | } | |
35 | 36 | |
36 | 37 | def make_bungie_request(self, url, access_token, kwargs): |
37 | 38 | """Helper function to get username data keyed off displayName""" |
38 | print('ENTERING MAKE BUNGIE REQUEST') | |
39 | 39 | headers = self.auth_headers() |
40 | print(repr(headers)) | |
41 | auth_header = {'Authorization': 'Bearer ' + access_token} | |
42 | headers.update(auth_header) | |
43 | import requests as python_requests | |
44 | r = python_requests.get(url, headers=headers) | |
45 | this_json = r.json() | |
46 | return this_json | |
40 | headers['Authorization'] = 'Bearer ' + access_token | |
41 | return self.get_json(url, headers=headers) | |
47 | 42 | |
48 | 43 | def auth_complete(self, *args, **kwargs): |
49 | 44 | """Completes login process, must return user instance""" |
57 | 52 | method=self.ACCESS_TOKEN_METHOD |
58 | 53 | ) |
59 | 54 | self.process_error(response) |
60 | return self.do_auth(response['access_token'], response=response, *args, **kwargs) | |
55 | return self.do_auth(response['access_token'], | |
56 | response=response, | |
57 | *args, **kwargs) | |
61 | 58 | |
62 | 59 | def do_auth(self, access_token, *args, **kwargs): |
63 | 60 | """Finish the auth process once the access_token was retrieved""" |
73 | 70 | """Grab user profile information from Bunige""" |
74 | 71 | membership_id = kwargs['response']['membership_id'] |
75 | 72 | url = 'https://www.bungie.net/Platform/User/GetBungieNetUser/' |
76 | this_json = self.make_bungie_request(url, access_token, kwargs) | |
77 | username = this_json['Response']['user']['displayName'] | |
78 | return {'username': username, 'uid': membership_id} | |
73 | response = self.make_bungie_request(url, access_token, kwargs) | |
74 | username = response['Response']['user']['displayName'] | |
75 | return {'username': username, | |
76 | 'uid': membership_id} | |
79 | 77 | |
80 | 78 | def get_user_details(self, response, *args, **kwargs): |
81 | 79 | """Return user details from Bungie account""" |
82 | 80 | username = response['username'] |
83 | uid = response['uid'] | |
84 | bnId = response['bnId'] | |
85 | 81 | return { |
86 | 82 | 'first_name': username, |
87 | 83 | 'username': username, |
88 | 'uid': uid, | |
84 | 'uid': response['uid'], | |
89 | 85 | } |
46 | 46 | """Return user data from Google API""" |
47 | 47 | return self.get_json( |
48 | 48 | 'https://www.googleapis.com/oauth2/v3/userinfo', |
49 | params={ | |
50 | 'access_token': access_token, | |
51 | 'alt': 'json' | |
52 | } | |
49 | headers={ | |
50 | 'Authorization': 'Bearer %s' % access_token, | |
51 | }, | |
53 | 52 | ) |
54 | 53 | |
55 | 54 | def revoke_token_params(self, token, uid): |
1 | 1 | import datetime |
2 | 2 | from calendar import timegm |
3 | 3 | |
4 | import six | |
4 | 5 | from jose import jwk, jwt |
5 | 6 | from jose.jwt import JWTError, JWTClaimsError, ExpiredSignatureError |
6 | 7 | from jose.utils import base64url_decode |
7 | import six | |
8 | ||
8 | 9 | from social_core.backends.oauth import BaseOAuth2 |
9 | 10 | from social_core.utils import cache |
10 | 11 | from social_core.exceptions import AuthTokenError |
42 | 43 | REVOKE_TOKEN_URL = '' |
43 | 44 | USERINFO_URL = '' |
44 | 45 | JWKS_URI = '' |
46 | JWT_DECODE_OPTIONS = dict() | |
45 | 47 | |
46 | 48 | def __init__(self, *args, **kwargs): |
47 | 49 | self.id_token = None |
146 | 148 | decoded_sig = base64url_decode(encoded_sig.encode('utf-8')) |
147 | 149 | if rsakey.verify(message.encode('utf-8'), decoded_sig): |
148 | 150 | return key |
149 | return False | |
150 | 151 | |
151 | 152 | def validate_and_return_id_token(self, id_token, access_token): |
152 | 153 | """ |
156 | 157 | client_id, client_secret = self.get_key_and_secret() |
157 | 158 | |
158 | 159 | key = self.find_valid_key(id_token) |
160 | ||
161 | if not key: | |
162 | raise AuthTokenError(self, 'Signature verification failed') | |
163 | ||
159 | 164 | alg = key['alg'] |
160 | 165 | rsakey = jwk.construct(key) |
161 | 166 | |
166 | 171 | algorithms=[alg], |
167 | 172 | audience=client_id, |
168 | 173 | issuer=self.id_token_issuer(), |
169 | access_token=access_token | |
174 | access_token=access_token, | |
175 | options=self.JWT_DECODE_OPTIONS, | |
170 | 176 | ) |
171 | 177 | except ExpiredSignatureError: |
172 | 178 | raise AuthTokenError(self, 'Signature has expired') |
173 | except JWTClaimsError: | |
174 | raise AuthTokenError(self, 'Invalid claims') | |
179 | except JWTClaimsError as error: | |
180 | raise AuthTokenError(self, str(error)) | |
175 | 181 | except JWTError: |
176 | 182 | raise AuthTokenError(self, 'Invalid signature') |
177 | 183 |
0 | from .oauth import BaseOAuth2 | |
1 | ||
2 | ||
3 | class UniverseOAuth2(BaseOAuth2): | |
4 | """Universe Ticketing OAuth2 authentication backend""" | |
5 | name = 'universe' | |
6 | AUTHORIZATION_URL = 'https://www.universe.com/oauth/authorize' | |
7 | ACCESS_TOKEN_URL = 'https://www.universe.com/oauth/token' | |
8 | BASE_API_URL = 'https://www.universe.com/api' | |
9 | USER_INFO_URL = BASE_API_URL + '/v2/current_user' | |
10 | ACCESS_TOKEN_METHOD = 'POST' | |
11 | STATE_PARAMETER = True | |
12 | REDIRECT_STATE = True | |
13 | EXTRA_DATA = [ | |
14 | ('id', 'id'), | |
15 | ('slug', 'slug'), | |
16 | ('created_at', 'created_at'), | |
17 | ('updated_at', 'updated_at'), | |
18 | ] | |
19 | ||
20 | def get_user_id(self, details, response): | |
21 | return response['current_user'][self.ID_KEY] | |
22 | ||
23 | def get_user_details(self, response): | |
24 | """Return user details from a Universe account""" | |
25 | # Start with the user data as it was returned | |
26 | user_details = response['current_user'] | |
27 | user_details['username'] = user_details['email'] | |
28 | return user_details | |
29 | ||
30 | def user_data(self, access_token, *args, **kwargs): | |
31 | """Loads user data from service""" | |
32 | return self.get_json(self.USER_INFO_URL, headers={ | |
33 | 'Authorization': 'Bearer {}'.format(access_token) | |
34 | }) |
0 | { | |
1 | "SOCIAL_AUTH_SAML_SP_ENTITY_ID": "https://github.com/omab/python-social-auth/saml-test", | |
2 | "SOCIAL_AUTH_SAML_SP_PUBLIC_CERT": "MIICsDCCAhmgAwIBAgIJAO7BwdjDZcUWMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNBMRkwFwYDVQQIExBCcml0aXNoIENvbHVtYmlhMRswGQYDVQQKExJweXRob24tc29jaWFsLWF1dGgwHhcNMTUwNTA4MDc1ODQ2WhcNMjUwNTA3MDc1ODQ2WjBFMQswCQYDVQQGEwJDQTEZMBcGA1UECBMQQnJpdGlzaCBDb2x1bWJpYTEbMBkGA1UEChMScHl0aG9uLXNvY2lhbC1hdXRoMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq3g1Cl+3uR5vCnN4HbgjTg+m3nHhteEMyb++ycZYre2bxUfsshER6x33l23tHckRYwm7MdBbrp3LrVoiOCdPblTml1IhEPTCwKMhBKvvWqTvgfcSSnRzAWkLlQYSusayyZK4n9qcYkV5MFni1rbjx+Mr5aOEmb5u33amMKLwSTwIDAQABo4GnMIGkMB0GA1UdDgQWBBRRiBR6zS66fKVokp0yJHbgv3RYmjB1BgNVHSMEbjBsgBRRiBR6zS66fKVokp0yJHbgv3RYmqFJpEcwRTELMAkGA1UEBhMCQ0ExGTAXBgNVBAgTEEJyaXRpc2ggQ29sdW1iaWExGzAZBgNVBAoTEnB5dGhvbi1zb2NpYWwtYXV0aIIJAO7BwdjDZcUWMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAJwsMU3YSaybVjuJ8US0fUhlPOlM40QFCGL4vB3TEbb24Mq8HrjUwrU0JFPGls9a2OYzN2B3e35NorMuxs+grGtr2yP6LvuX+nV6A93wb4ooGHoGfC7VLlyxSSns937SS5R1pzQ4gWzZma2KGWKICWph5zQ0ARVhL63967mGLmoI=", | |
3 | "SOCIAL_AUTH_SAML_SP_PRIVATE_KEY": "MIICXgIBAAKBgQCq3g1Cl+3uR5vCnN4HbgjTg+m3nHhteEMyb++ycZYre2bxUfsshER6x33l23tHckRYwm7MdBbrp3LrVoiOCdPblTml1IhEPTCwKMhBKvvWqTvgfcSSnRzAWkLlQYSusayyZK4n9qcYkV5MFni1rbjx+Mr5aOEmb5u33amMKLwSTwIDAQABAoGBAIHAg6NJSiYC/NYpVzWfKlasuoNy78R5adXYSNZiCR5V5FNm5OzmODZgXUt6g0A7FomshIT/txQWoV7y5FmwPs8n13JY3Hdt4tJ6MHw2feLo710+OEp9VBQus3JsB2F8ONYrGvs00hPPL7h5av/rzTdE8F67YM1mSgeg7xEF6BghAkEA12OOqSzp2MLTNY7PqOaLDzy4aAMVNN3Ntv2jBN0jq7s1b5ilQ2PGkLwdtkicq/VZcRyUqVbZbMwz05II3nqx3wJBAMsVhRQ5sdFCRBzEbSAm2YEJaFh5u6QT3+zWHMFpPJRnaBAWz3RXKEnleJ+DS2Xz1Jm6ZrmLdZiwMx/8dK5rDZECQQC7GTdWi7ZC3dIcpwaKIGHRhZxmda8ZMkc9Wwwd8H7I8aFUZFPCu0xEc7SXoHHACit8zyfwBYpvMN8gPK3JnOkfAkEAsUSpk0wBMT38one7IZOHzCDgGkq4RbKrhdon45Pus0PIDDM9BrqFimtpbSN4DxhVfZK91DwtfAhhuAvv9cewYQJAPMhpAqv3PBGYmtRDUlWXJQv2JRJJkrvbbqgBed2OX5RRgj5V3SR6PBhLbcTZ+q+1tdPkMFzZo5U6MN5m/6oXvQ==", | |
4 | "SOCIAL_AUTH_SAML_ORG_INFO": { | |
5 | "en-US": {"name": "psa", "displayname": "PSA", "url": "https://github.com/omab/python-social-auth/"} | |
6 | }, | |
7 | "SOCIAL_AUTH_SAML_TECHNICAL_CONTACT": | |
8 | {"givenName": "Tech Gal", "emailAddress": "technical@example.com"}, | |
9 | "SOCIAL_AUTH_SAML_SUPPORT_CONTACT": | |
10 | {"givenName": "Support Guy", "emailAddress": "support@example.com"}, | |
11 | "SOCIAL_AUTH_SAML_ENABLED_IDPS": { | |
12 | "testshib": { | |
13 | "entity_id": "https://idp.testshib.org/idp/shibboleth", | |
14 | "url": "https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO", | |
15 | "x509cert": "MIIEDjCCAvagAwIBAgIBADANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzEVMBMGA1UECBMMUGVubnN5bHZhbmlhMRMwEQYDVQQHEwpQaXR0c2J1cmdoMREwDwYDVQQKEwhUZXN0U2hpYjEZMBcGA1UEAxMQaWRwLnRlc3RzaGliLm9yZzAeFw0wNjA4MzAyMTEyMjVaFw0xNjA4MjcyMTEyMjVaMGcxCzAJBgNVBAYTAlVTMRUwEwYDVQQIEwxQZW5uc3lsdmFuaWExEzARBgNVBAcTClBpdHRzYnVyZ2gxETAPBgNVBAoTCFRlc3RTaGliMRkwFwYDVQQDExBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArYkCGuTmJp9eAOSGHwRJo1SNatB5ZOKqDM9ysg7CyVTDClcpu93gSP10nH4gkCZOlnESNgttg0r+MqL8tfJC6ybddEFB3YBo8PZajKSe3OQ01Ow3yT4I+Wdg1tsTpSge9gEz7SrC07EkYmHuPtd71CHiUaCWDv+xVfUQX0aTNPFmDixzUjoYzbGDrtAyCqA8f9CN2txIfJnpHE6q6CmKcoLADS4UrNPlhHSzd614kR/JYiks0K4kbRqCQF0Dv0P5Di+rEfefC6glV8ysC8dB5/9nb0yh/ojRuJGmgMWHgWk6h0ihjihqiu4jACovUZ7vVOCgSE5Ipn7OIwqd93zp2wIDAQABo4HEMIHBMB0GA1UdDgQWBBSsBQ869nh83KqZr5jArr4/7b+QazCBkQYDVR0jBIGJMIGGgBSsBQ869nh83KqZr5jArr4/7b+Qa6FrpGkwZzELMAkGA1UEBhMCVVMxFTATBgNVBAgTDFBlbm5zeWx2YW5pYTETMBEGA1UEBxMKUGl0dHNidXJnaDERMA8GA1UEChMIVGVzdFNoaWIxGTAXBgNVBAMTEGlkcC50ZXN0c2hpYi5vcmeCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAjR29PhrCbk8qLN5MFfSVk98t3CT9jHZoYxd8QMRLI4j7iYQxXiGJTT1FXs1nd4Rha9un+LqTfeMMYqISdDDI6tv8iNpkOAvZZUosVkUo93pv1T0RPz35hcHHYq2yee59HJOco2bFlcsH8JBXRSRrJ3Q7Eut+z9uo80JdGNJ4/SJy5UorZ8KazGj16lfJhOBXldgrhppQBb0Nq6HKHguqmwRfJ+WkxemZXzhediAjGeka8nz8JjwxpUjAiSWYKLtJhGEaTqCYxCCX2Dw+dOTqUzHOZ7WKv4JXPK5G/Uhr8K/qhmFT2nIQi538n6rVYLeWj8Bbnl+ev0peYzxFyF5sQA==" | |
16 | }, | |
17 | "other": { | |
18 | "entity_id": "https://unused.saml.example.com", | |
19 | "url": "https://unused.saml.example.com/SAML2/Redirect/SSO" | |
20 | } | |
21 | } | |
22 | } |
0 | 0 | # -*- coding: utf-8 -*- |
1 | from calendar import timegm | |
2 | ||
3 | 1 | import os |
4 | 2 | import sys |
5 | 3 | import json |
6 | 4 | import datetime |
7 | 5 | import unittest2 |
6 | import base64 | |
7 | from calendar import timegm | |
8 | 8 | |
9 | try: | |
10 | from jwkest.jwk import RSAKey, KEYS | |
11 | from jwkest.jws import JWS | |
12 | from jwkest.jwt import b64encode_item | |
13 | NO_JWKEST = False | |
14 | except ImportError: | |
15 | NO_JWKEST = True | |
16 | ||
9 | from jose import jwt | |
10 | from jose.jwk import RSAKey | |
17 | 11 | from httpretty import HTTPretty |
18 | 12 | |
19 | 13 | sys.path.insert(0, '..') |
20 | 14 | |
21 | 15 | from ...exceptions import AuthTokenError |
16 | ||
17 | ||
18 | TEST_ROOT = os.path.dirname(os.path.dirname(__file__)) | |
19 | ||
20 | JWK_KEY = { | |
21 | 'kty': 'RSA', | |
22 | 'd': 'ZmswNokEvBcxW_Kvcy8mWUQOQCBdGbnM0xR7nhvGHC-Q24z3XAQWlMWbsmGc_R1o' \ | |
23 | '_F3zK7DBlc3BokdRaO1KJirNmnHCw5TlnBlJrXiWpFBtVglUg98-4sRRO0VWnGXK' \ | |
24 | 'JPOkBQ6b_DYRO3b0o8CSpWowpiV6HB71cjXTqKPZf-aXU9WjCCAtxVjfIxgQFu5I' \ | |
25 | '-G1Qah8mZeY8HK_y99L4f0siZcbUoaIcfeWBhxi14ODyuSAHt0sNEkhiIVBZE7QZ' \ | |
26 | 'm-SEP1ryT9VAaljbwHHPmg7NC26vtLZhvaBGbTTJnEH0ZubbN2PMzsfeNyoCIHy4' \ | |
27 | '4QDSpQDCHfgcGOlHY_t5gQ', | |
28 | 'e': 'AQAB', | |
29 | 'use': 'sig', | |
30 | 'kid': 'testkey', | |
31 | 'alg': 'RS256', | |
32 | 'n': 'pUfcJ8WFrVue98Ygzb6KEQXHBzi8HavCu8VENB2As943--bHPcQ-nScXnrRFAUg8' \ | |
33 | 'H5ZltuOcHWvsGw_AQifSLmOCSWJAPkdNb0w0QzY7Re8NrPjCsP58Tytp5LicF0Ao' \ | |
34 | 'Ag28UK3JioY9hXHGvdZsWR1Rp3I-Z3nRBP6HyO18pEgcZ91c9aAzsqu80An9X4DA' \ | |
35 | 'b1lExtZorvcd5yTBzZgr-MUeytVRni2lDNEpa6OFuopHXmg27Hn3oWAaQlbymd4g' \ | |
36 | 'ifc01oahcwl3ze2tMK6gJxa_TdCf1y99Yq6oilmVvZJ8kwWWnbPE-oDmOVPVnEyT' \ | |
37 | 'vYVCvN4rBT1DQ-x0F1mo2Q', | |
38 | } | |
39 | ||
40 | JWK_PUBLIC_KEY = {key: value for key, value in JWK_KEY.items() if key != 'd'} | |
22 | 41 | |
23 | 42 | |
24 | 43 | class OpenIdConnectTestMixin(object): |
34 | 53 | |
35 | 54 | def setUp(self): |
36 | 55 | super(OpenIdConnectTestMixin, self).setUp() |
37 | test_root = os.path.dirname(os.path.dirname(__file__)) | |
38 | self.key = RSAKey(kid='testkey').load(os.path.join(test_root, 'testkey.pem')) | |
56 | self.key = JWK_KEY.copy() | |
57 | self.public_key = JWK_PUBLIC_KEY.copy() | |
58 | ||
39 | 59 | HTTPretty.register_uri(HTTPretty.GET, |
40 | 60 | self.backend.OIDC_ENDPOINT + '/.well-known/openid-configuration', |
41 | 61 | status=200, |
44 | 64 | oidc_config = json.loads(self.openid_config_body) |
45 | 65 | |
46 | 66 | def jwks(_request, _uri, headers): |
47 | ks = KEYS() | |
48 | ks.add(self.key.serialize()) | |
49 | return 200, headers, ks.dump_jwks() | |
67 | return 200, headers, json.dumps({'keys': [self.key]}) | |
50 | 68 | |
51 | 69 | HTTPretty.register_uri(HTTPretty.GET, |
52 | 70 | oidc_config.get('jwks_uri'), |
53 | 71 | status=200, |
54 | body=jwks) | |
72 | body=json.dumps({'keys': [self.public_key]})) | |
55 | 73 | |
56 | 74 | def extra_settings(self): |
57 | 75 | settings = super(OpenIdConnectTestMixin, self).extra_settings() |
62 | 80 | self.client_secret |
63 | 81 | }) |
64 | 82 | return settings |
65 | ||
66 | def access_token_body(self, request, _url, headers): | |
67 | """ | |
68 | Get the nonce from the request parameters, add it to the id_token, and | |
69 | return the complete response. | |
70 | """ | |
71 | nonce = self.backend.data['nonce'].encode('utf-8') | |
72 | body = self.prepare_access_token_body(nonce=nonce) | |
73 | return 200, headers, body | |
74 | 83 | |
75 | 84 | def get_id_token(self, client_key=None, expiration_datetime=None, |
76 | 85 | issue_datetime=None, nonce=None, issuer=None): |
109 | 118 | nonce = nonce or 'a-nonce' |
110 | 119 | issuer = issuer or self.issuer |
111 | 120 | id_token = self.get_id_token( |
112 | client_key, timegm(expiration_datetime.utctimetuple()), | |
113 | timegm(issue_datetime.utctimetuple()), nonce, issuer) | |
121 | client_key, | |
122 | timegm(expiration_datetime.utctimetuple()), | |
123 | timegm(issue_datetime.utctimetuple()), | |
124 | nonce, | |
125 | issuer | |
126 | ) | |
114 | 127 | |
115 | body['id_token'] = JWS(id_token, jwk=self.key, alg='RS256').sign_compact() | |
128 | body['id_token'] = jwt.encode( | |
129 | id_token, | |
130 | key=dict(self.key, | |
131 | iat=timegm(issue_datetime.utctimetuple()), | |
132 | nonce=nonce), | |
133 | algorithm='RS256', | |
134 | access_token='foobar' | |
135 | ) | |
136 | ||
116 | 137 | if tamper_message: |
117 | 138 | header, msg, sig = body['id_token'].split('.') |
118 | 139 | id_token['sub'] = '1235' |
119 | msg = b64encode_item(id_token).decode('utf-8') | |
140 | msg = base64.encodestring(json.dumps(id_token).encode()).decode() | |
120 | 141 | body['id_token'] = '.'.join([header, msg, sig]) |
121 | 142 | |
122 | 143 | return json.dumps(body) |
128 | 149 | with self.assertRaisesRegexp(AuthTokenError, expected_message): |
129 | 150 | self.do_login() |
130 | 151 | |
131 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
132 | 152 | def test_invalid_signature(self): |
133 | 153 | self.authtoken_raised( |
134 | 154 | 'Token error: Signature verification failed', |
135 | 155 | tamper_message=True |
136 | 156 | ) |
137 | 157 | |
138 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
139 | 158 | def test_expired_signature(self): |
140 | 159 | expiration_datetime = datetime.datetime.utcnow() - \ |
141 | 160 | datetime.timedelta(seconds=30) |
142 | 161 | self.authtoken_raised('Token error: Signature has expired', |
143 | 162 | expiration_datetime=expiration_datetime) |
144 | 163 | |
145 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
146 | 164 | def test_invalid_issuer(self): |
147 | 165 | self.authtoken_raised('Token error: Invalid issuer', |
148 | 166 | issuer='someone-else') |
149 | 167 | |
150 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
151 | 168 | def test_invalid_audience(self): |
152 | 169 | self.authtoken_raised('Token error: Invalid audience', |
153 | 170 | client_key='someone-else') |
154 | 171 | |
155 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
156 | 172 | def test_invalid_issue_time(self): |
157 | 173 | expiration_datetime = datetime.datetime.utcnow() - \ |
158 | 174 | datetime.timedelta(hours=1) |
159 | 175 | self.authtoken_raised('Token error: Incorrect id_token: iat', |
160 | 176 | issue_datetime=expiration_datetime) |
161 | 177 | |
162 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
163 | 178 | def test_invalid_nonce(self): |
164 | 179 | self.authtoken_raised( |
165 | 180 | 'Token error: Incorrect id_token: nonce', |
0 | ||
1 | import json | |
2 | ||
3 | from jose import jwt | |
4 | from httpretty import HTTPretty | |
5 | ||
6 | from .oauth import OAuth2Test | |
7 | ||
8 | JWK_KEY = { | |
9 | 'kty': 'RSA', | |
10 | 'd': 'ZmswNokEvBcxW_Kvcy8mWUQOQCBdGbnM0xR7nhvGHC-Q24z3XAQWlMWbsmGc_R1o' \ | |
11 | '_F3zK7DBlc3BokdRaO1KJirNmnHCw5TlnBlJrXiWpFBtVglUg98-4sRRO0VWnGXK' \ | |
12 | 'JPOkBQ6b_DYRO3b0o8CSpWowpiV6HB71cjXTqKPZf-aXU9WjCCAtxVjfIxgQFu5I' \ | |
13 | '-G1Qah8mZeY8HK_y99L4f0siZcbUoaIcfeWBhxi14ODyuSAHt0sNEkhiIVBZE7QZ' \ | |
14 | 'm-SEP1ryT9VAaljbwHHPmg7NC26vtLZhvaBGbTTJnEH0ZubbN2PMzsfeNyoCIHy4' \ | |
15 | '4QDSpQDCHfgcGOlHY_t5gQ', | |
16 | 'e': 'AQAB', | |
17 | 'use': 'sig', | |
18 | 'kid': 'foobar', | |
19 | 'alg': 'RS256', | |
20 | 'n': 'pUfcJ8WFrVue98Ygzb6KEQXHBzi8HavCu8VENB2As943--bHPcQ-nScXnrRFAUg8' \ | |
21 | 'H5ZltuOcHWvsGw_AQifSLmOCSWJAPkdNb0w0QzY7Re8NrPjCsP58Tytp5LicF0Ao' \ | |
22 | 'Ag28UK3JioY9hXHGvdZsWR1Rp3I-Z3nRBP6HyO18pEgcZ91c9aAzsqu80An9X4DA' \ | |
23 | 'b1lExtZorvcd5yTBzZgr-MUeytVRni2lDNEpa6OFuopHXmg27Hn3oWAaQlbymd4g' \ | |
24 | 'ifc01oahcwl3ze2tMK6gJxa_TdCf1y99Yq6oilmVvZJ8kwWWnbPE-oDmOVPVnEyT' \ | |
25 | 'vYVCvN4rBT1DQ-x0F1mo2Q' | |
26 | } | |
27 | ||
28 | JWK_PUBLIC_KEY = {key: value for key, value in JWK_KEY.items() if key != 'd'} | |
29 | ||
30 | DOMAIN = 'foobar.auth0.com' | |
31 | ||
32 | ||
33 | class Auth0OAuth2Test(OAuth2Test): | |
34 | backend_path = 'social_core.backends.auth0.Auth0OAuth2' | |
35 | access_token_body = json.dumps({ | |
36 | 'access_token': 'foobar', | |
37 | 'token_type': 'bearer', | |
38 | 'expires_in': 86400, | |
39 | 'id_token': jwt.encode({ | |
40 | 'nickname': 'foobar', | |
41 | 'email': 'foobar@auth0.com', | |
42 | 'name': 'John Doe', | |
43 | 'picture': 'http://example.com/image.png', | |
44 | 'sub': '123456', | |
45 | 'iss': 'https://{}/'.format(DOMAIN), | |
46 | }, JWK_KEY, algorithm='RS256') | |
47 | }) | |
48 | expected_username = 'foobar' | |
49 | jwks_url = 'https://foobar.auth0.com/.well-known/jwks.json' | |
50 | ||
51 | def extra_settings(self): | |
52 | settings = super(Auth0OAuth2Test, self).extra_settings() | |
53 | settings['SOCIAL_AUTH_' + self.name + '_DOMAIN'] = DOMAIN | |
54 | return settings | |
55 | ||
56 | def auth_handlers(self, start_url): | |
57 | HTTPretty.register_uri(HTTPretty.GET, | |
58 | self.jwks_url, | |
59 | body=json.dumps({'keys': [JWK_PUBLIC_KEY]}), | |
60 | content_type='application/json') | |
61 | return super(Auth0OAuth2Test, self).auth_handlers(start_url) | |
62 | ||
63 | def test_login(self): | |
64 | self.do_login() | |
65 | ||
66 | def test_partial_pipeline(self): | |
67 | self.do_partial_pipeline() |
22 | 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | 23 | SOFTWARE. |
24 | 24 | """ |
25 | ||
26 | ||
27 | 25 | import json |
28 | 26 | import jwt |
29 | 27 | |
30 | 28 | from time import time |
31 | from unittest import SkipTest | |
32 | 29 | from httpretty import HTTPretty |
30 | from jwt.algorithms import RSAAlgorithm | |
33 | 31 | |
34 | 32 | from .oauth import OAuth2Test |
35 | ||
36 | ||
37 | try: | |
38 | from jwt.algorithms import RSAAlgorithm | |
39 | except ImportError: | |
40 | # Usually in Python 3.3 | |
41 | raise SkipTest('RSA support is missing in jwt/cryptography packages') | |
42 | ||
43 | 33 | |
44 | 34 | |
45 | 35 | # Dummy private and private keys: |
0 | 0 | import unittest2 |
1 | 1 | |
2 | 2 | from .oauth import OAuth1Test, OAuth2Test |
3 | from .open_id_connect import OpenIdConnectTestMixin, NO_JWKEST | |
3 | from .open_id_connect import OpenIdConnectTestMixin | |
4 | 4 | |
5 | 5 | |
6 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
7 | 6 | class ElixirOpenIdConnectTest(OpenIdConnectTestMixin, OAuth2Test): |
8 | 7 | backend_path = 'social_core.backends.elixir.ElixirOpenIdConnect' |
9 | 8 | issuer = 'https://login.elixir-czech.org/oidc/' |
0 | import json | |
0 | 1 | import unittest2 |
1 | 2 | |
2 | 3 | from .oauth import OAuth1Test, OAuth2Test |
3 | from .open_id_connect import OpenIdConnectTestMixin, NO_JWKEST | |
4 | from .open_id_connect import OpenIdConnectTestMixin | |
4 | 5 | |
5 | 6 | |
6 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
7 | 7 | class GlobusOpenIdConnectTest(OpenIdConnectTestMixin, OAuth2Test): |
8 | 8 | backend_path = \ |
9 | 9 | 'social_core.backends.globus.GlobusOpenIdConnect' |
10 | 10 | issuer = 'https://auth.globus.org' |
11 | openid_config_body = ''.join([ | |
12 | '{' | |
13 | ' "issuer": "https://auth.globus.org",' | |
14 | ' "authorization_endpoint": "https://auth.globus.org/v2/oauth2/authorize",' | |
15 | ' "userinfo_endpoint": "https://auth.globus.org/v2/oauth2/userinfo",' | |
16 | ' "token_endpoint": "https://auth.globus.org/v2/oauth2/token",' | |
17 | ' "revocation_endpoint": "https://auth.globus.org/v2/oauth2/token/revoke",' | |
18 | ' "jwks_uri": "https://auth.globus.org/jwk.json",' | |
19 | ' "response_types_supported": [' | |
20 | ' "code",' | |
21 | ' "token",' | |
22 | ' "token id_token",' | |
23 | ' "id_token"' | |
24 | ' ],' | |
25 | ' "id_token_signing_alg_values_supported": [' | |
26 | ' "RS512"' | |
27 | ' ],' | |
28 | ' "scopes_supported": [' | |
29 | ' "openid",' | |
30 | ' "email",' | |
31 | ' "profile"' | |
32 | ' ],' | |
33 | ' "token_endpoint_auth_methods_supported": [' | |
34 | ' "client_secret_basic"' | |
35 | ' ],' | |
36 | ' "claims_supported": [' | |
37 | ' "at_hash",' | |
38 | ' "aud",' | |
39 | ' "email",' | |
40 | ' "exp",' | |
41 | ' "name",' | |
42 | ' "nonce",' | |
43 | ' "preferred_username",' | |
44 | ' "iat",' | |
45 | ' "iss",' | |
46 | ' "sub"' | |
47 | ' ],' | |
48 | ' "subject_types_supported" : ["public"]' | |
49 | '}' | |
50 | ]) | |
11 | openid_config_body = json.dumps({ | |
12 | 'issuer': 'https://auth.globus.org', | |
13 | 'authorization_endpoint': 'https://auth.globus.org/v2/oauth2/authorize', | |
14 | 'userinfo_endpoint': 'https://auth.globus.org/v2/oauth2/userinfo', | |
15 | 'token_endpoint': 'https://auth.globus.org/v2/oauth2/token', | |
16 | 'revocation_endpoint': 'https://auth.globus.org/v2/oauth2/token/revoke', | |
17 | 'jwks_uri': 'https://auth.globus.org/jwk.json', | |
18 | 'response_types_supported': [ | |
19 | 'code', | |
20 | 'token', | |
21 | 'token id_token', | |
22 | 'id_token' | |
23 | ], | |
24 | 'id_token_signing_alg_values_supported': [ | |
25 | 'RS512' | |
26 | ], | |
27 | 'scopes_supported': [ | |
28 | 'openid', | |
29 | 'email', | |
30 | 'profile' | |
31 | ], | |
32 | 'token_endpoint_auth_methods_supported': [ | |
33 | 'client_secret_basic' | |
34 | ], | |
35 | 'claims_supported': [ | |
36 | 'at_hash', | |
37 | 'aud', | |
38 | 'email', | |
39 | 'exp', | |
40 | 'name', | |
41 | 'nonce', | |
42 | 'preferred_username', | |
43 | 'iat', | |
44 | 'iss', | |
45 | 'sub' | |
46 | ], | |
47 | 'subject_types_supported' : ['public'] | |
48 | }) |
10 | 10 | from ..models import User |
11 | 11 | from .oauth import OAuth1Test, OAuth2Test |
12 | 12 | from .open_id import OpenIdTest |
13 | from .open_id_connect import OpenIdConnectTestMixin, NO_JWKEST | |
13 | from .open_id_connect import OpenIdConnectTestMixin | |
14 | 14 | |
15 | 15 | |
16 | 16 | class GoogleOAuth2Test(OAuth2Test): |
36 | 36 | |
37 | 37 | def test_login(self): |
38 | 38 | self.do_login() |
39 | last_request = HTTPretty.last_request | |
40 | self.assertEqual(last_request.method, 'GET') | |
41 | self.assertTrue(self.user_data_url.endswith(last_request.path)) | |
42 | self.assertEqual( | |
43 | last_request.headers['Authorization'], | |
44 | 'Bearer foobar', | |
45 | ) | |
46 | self.assertEqual(last_request.querystring, {}) | |
39 | 47 | |
40 | 48 | def test_partial_pipeline(self): |
41 | 49 | self.do_partial_pipeline() |
194 | 202 | do_disconnect(self.backend, user) |
195 | 203 | |
196 | 204 | |
197 | @unittest2.skipIf(NO_JWKEST, 'No Jwkest installed') | |
198 | class GoogleOpenIdConnectTest(OpenIdConnectTestMixin, GoogleOAuth2Test): | |
205 | class GoogleOpenIdConnectTest(OpenIdConnectTestMixin, OAuth2Test): | |
199 | 206 | backend_path = \ |
200 | 207 | 'social_core.backends.google_openidconnect.GoogleOpenIdConnect' |
201 | 208 | user_data_url = \ |
202 | 209 | 'https://www.googleapis.com/plus/v1/people/me/openIdConnect' |
203 | 210 | issuer = 'accounts.google.com' |
204 | openid_config_body = ''.join([ | |
205 | '{', | |
206 | ' "issuer": "https://accounts.google.com",', | |
207 | ' "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",', | |
208 | ' "token_endpoint": "https://www.googleapis.com/oauth2/v4/token",', | |
209 | ' "userinfo_endpoint": "https://www.googleapis.com/oauth2/v3/userinfo",', | |
210 | ' "revocation_endpoint": "https://accounts.google.com/o/oauth2/revoke",', | |
211 | ' "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",', | |
212 | ' "response_types_supported": [', | |
213 | ' "code",', | |
214 | ' "token",', | |
215 | ' "id_token",', | |
216 | ' "code token",', | |
217 | ' "code id_token",', | |
218 | ' "token id_token",', | |
219 | ' "code token id_token",', | |
220 | ' "none"', | |
221 | ' ],', | |
222 | ' "subject_types_supported": [', | |
223 | ' "public"', | |
224 | ' ],', | |
225 | ' "id_token_signing_alg_values_supported": [', | |
226 | ' "RS256"', | |
227 | ' ],', | |
228 | ' "scopes_supported": [', | |
229 | ' "openid",', | |
230 | ' "email",', | |
231 | ' "profile"', | |
232 | ' ],', | |
233 | ' "token_endpoint_auth_methods_supported": [', | |
234 | ' "client_secret_post",', | |
235 | ' "client_secret_basic"', | |
236 | ' ],', | |
237 | ' "claims_supported": [', | |
238 | ' "aud",', | |
239 | ' "email",', | |
240 | ' "email_verified",', | |
241 | ' "exp",', | |
242 | ' "family_name",', | |
243 | ' "given_name",', | |
244 | ' "iat",', | |
245 | ' "iss",', | |
246 | ' "locale",', | |
247 | ' "name",', | |
248 | ' "picture",', | |
249 | ' "sub"', | |
250 | ' ]', | |
251 | '}' | |
252 | ]) | |
211 | openid_config_body = json.dumps({ | |
212 | 'issuer': 'https://accounts.google.com', | |
213 | 'authorization_endpoint': 'https://accounts.google.com/o/oauth2/v2/auth', | |
214 | 'token_endpoint': 'https://www.googleapis.com/oauth2/v4/token', | |
215 | 'userinfo_endpoint': 'https://www.googleapis.com/oauth2/v3/userinfo', | |
216 | 'revocation_endpoint': 'https://accounts.google.com/o/oauth2/revoke', | |
217 | 'jwks_uri': 'https://www.googleapis.com/oauth2/v3/certs', | |
218 | 'response_types_supported': [ | |
219 | 'code', | |
220 | 'token', | |
221 | 'id_token', | |
222 | 'code token', | |
223 | 'code id_token', | |
224 | 'token id_token', | |
225 | 'code token id_token', | |
226 | 'none', | |
227 | ], | |
228 | 'subject_types_supported': [ | |
229 | 'public', | |
230 | ], | |
231 | 'id_token_signing_alg_values_supported': [ | |
232 | 'RS256', | |
233 | ], | |
234 | 'scopes_supported': [ | |
235 | 'openid', | |
236 | 'email', | |
237 | 'profile', | |
238 | ], | |
239 | 'token_endpoint_auth_methods_supported': [ | |
240 | 'client_secret_post', | |
241 | 'client_secret_basic', | |
242 | ], | |
243 | 'claims_supported': [ | |
244 | 'aud', | |
245 | 'email', | |
246 | 'email_verified', | |
247 | 'exp', | |
248 | 'family_name', | |
249 | 'given_name', | |
250 | 'iat', | |
251 | 'iss', | |
252 | 'locale', | |
253 | 'name', | |
254 | 'picture', | |
255 | 'sub', | |
256 | ], | |
257 | }) |
4 | 4 | import jwt |
5 | 5 | |
6 | 6 | from .oauth import OAuth2Test |
7 | ||
8 | try: | |
9 | from jwt.algorithms import RSAAlgorithm | |
10 | except ImportError: | |
11 | # Usually in Python 3.3 | |
12 | raise unittest.SkipTest('RSA support is missing in jwt/cryptography packages') | |
13 | 7 | |
14 | 8 | |
15 | 9 | _PRIVATE_KEY_HEADERLESS = ''' |
0 | import json | |
1 | ||
2 | from .oauth import OAuth2Test | |
3 | ||
4 | ||
5 | class UniverseAuth2Test(OAuth2Test): | |
6 | backend_path = 'social_core.backends.universe.UniverseOAuth2' | |
7 | user_data_url = 'https://www.universe.com/api/v2/current_user' | |
8 | expected_username = 'scott+awesome@universe.com' | |
9 | access_token_body = json.dumps({ | |
10 | 'access_token': 'foobar', | |
11 | 'token_type': 'bearer' | |
12 | }) | |
13 | user_data_body = json.dumps( | |
14 | { | |
15 | 'current_user': { | |
16 | 'id': '123456', | |
17 | 'slug': 'scott-vitale', | |
18 | 'first_name': 'Scott', | |
19 | 'last_name': 'Vitale', | |
20 | 'created_at': '2019-01-08T15:49:42.514Z', | |
21 | 'updated_at': '2019-01-17T19:41:39.711Z', | |
22 | 'email': 'scott+awesome@universe.com', | |
23 | } | |
24 | } | |
25 | ) | |
26 | ||
27 | def test_login(self): | |
28 | self.do_login() | |
29 | ||
30 | def test_partial_pipeline(self): | |
31 | self.do_partial_pipeline() |
0 | # Tox (http://tox.testrun.org/) is a tool for running tests | |
1 | # in multiple virtualenvs. This configuration file will run the | |
2 | # test suite on all supported python versions. To use it, "pip install tox" | |
3 | # and then run "tox" from this directory. | |
4 | ||
5 | [tox] | |
6 | # py36 fails due to python3-openid tries to use a removed xml module, | |
7 | # once that's fixed it can be enabled again | |
8 | envlist = py27,py34,py35,py36,pypy | |
9 | ||
10 | [testenv] | |
11 | passenv = * | |
12 | commands = nosetests {posargs} | |
13 | deps = | |
14 | py{27,py}: -rsocial_core/tests/requirements-python2.txt | |
15 | py3{4,5,6}: -rsocial_core/tests/requirements-python3.txt | |
16 | extras = all |