├── 01-Login ├── Procfile ├── .gitignore ├── .dockerignore ├── requirements.txt ├── exec.sh ├── exec.ps1 ├── .env.example ├── Dockerfile ├── constants.py ├── templates │ ├── home.html │ └── dashboard.html ├── public │ └── app.css ├── README.md └── server.py ├── .github ├── CODEOWNERS └── stale.yml ├── .gitignore ├── LICENSE ├── README.md └── .circleci └── config.yml /01-Login/Procfile: -------------------------------------------------------------------------------- 1 | web: python server.py -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @auth0-samples/dx-sdks-approver 2 | -------------------------------------------------------------------------------- /01-Login/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .pyc 3 | *.iml 4 | .directory 5 | .idea -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.iml 3 | .idea 4 | .env 5 | __pycache__ 6 | -------------------------------------------------------------------------------- /01-Login/.dockerignore: -------------------------------------------------------------------------------- 1 | .env 2 | .env.example 3 | .gitignore 4 | .git 5 | README.md -------------------------------------------------------------------------------- /01-Login/requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | python-dotenv 3 | requests 4 | authlib>=0.14.1 5 | six 6 | -------------------------------------------------------------------------------- /01-Login/exec.sh: -------------------------------------------------------------------------------- 1 | docker build -t auth0-python-web-01-login . 2 | docker run --env-file .env -p 3000:3000 -it auth0-python-web-01-login 3 | -------------------------------------------------------------------------------- /01-Login/exec.ps1: -------------------------------------------------------------------------------- 1 | docker build -t auth0-python-web-01-login . 2 | docker run --env-file .env -p 3000:3000 -it auth0-python-web-01-login 3 | -------------------------------------------------------------------------------- /01-Login/.env.example: -------------------------------------------------------------------------------- 1 | AUTH0_CLIENT_ID={CLIENT_ID} 2 | AUTH0_DOMAIN={DOMAIN} 3 | AUTH0_CLIENT_SECRET={CLIENT_SECRET} 4 | AUTH0_CALLBACK_URL=http://localhost:3000/callback 5 | AUTH0_AUDIENCE= 6 | -------------------------------------------------------------------------------- /01-Login/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3 2 | 3 | WORKDIR /home/app 4 | 5 | #If we add the requirements and install dependencies first, docker can use cache if requirements don't change 6 | ADD requirements.txt /home/app 7 | RUN pip install --no-cache-dir -r requirements.txt 8 | 9 | ADD . /home/app 10 | CMD python server.py 11 | 12 | EXPOSE 3000 13 | -------------------------------------------------------------------------------- /01-Login/constants.py: -------------------------------------------------------------------------------- 1 | """ Constants file for Auth0's seed project 2 | """ 3 | AUTH0_CLIENT_ID = 'AUTH0_CLIENT_ID' 4 | AUTH0_CLIENT_SECRET = 'AUTH0_CLIENT_SECRET' 5 | AUTH0_CALLBACK_URL = 'AUTH0_CALLBACK_URL' 6 | AUTH0_DOMAIN = 'AUTH0_DOMAIN' 7 | AUTH0_AUDIENCE = 'AUTH0_AUDIENCE' 8 | PROFILE_KEY = 'profile' 9 | SECRET_KEY = 'ThisIsTheSecretKey' 10 | JWT_PAYLOAD = 'jwt_payload' 11 | 12 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 90 5 | 6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. 7 | daysUntilClose: 7 8 | 9 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 10 | exemptLabels: [] 11 | 12 | # Set to true to ignore issues with an assignee (defaults to false) 13 | exemptAssignees: true 14 | 15 | # Label to use when marking as stale 16 | staleLabel: closed:stale 17 | 18 | # Comment to post when marking as stale. Set to `false` to disable 19 | markComment: > 20 | This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you have not received a response for our team (apologies for the delay) and this is still a blocker, please reply with additional information or just a ping. Thank you for your contribution! 🙇‍♂️ -------------------------------------------------------------------------------- /01-Login/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 | 21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Auth0 Samples 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /01-Login/templates/dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |

15 | 16 |

Welcome {{userinfo['name']}}

17 |
{{userinfo_pretty}}
18 | Logout 19 |
20 |
21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Auth0 Python Web App 2 | 3 | [![CircleCI](https://circleci.com/gh/auth0-samples/auth0-python-web-app.svg?style=svg)](https://circleci.com/gh/auth0-samples/auth0-python-web-app) 4 | 5 | This repository contains the source code for the [Python Web App Quickstart](https://auth0.com/docs/quickstart/webapp/python). 6 | 7 | ## What is Auth0? 8 | 9 | Auth0 helps you to easily: 10 | 11 | - implement authentication with multiple identity providers, including social (e.g., Google, Facebook, Microsoft, LinkedIn, GitHub, Twitter, etc), or enterprise (e.g., Windows Azure AD, Google Apps, Active Directory, ADFS, SAML, etc.) 12 | - log in users with username/password databases, passwordless, or multi-factor authentication 13 | - link multiple user accounts together 14 | - generate signed JSON Web Tokens to authorize your API calls and flow the user identity securely 15 | - access demographics and analytics detailing how, when, and where users are logging in 16 | - enrich user profiles from other data sources using customizable JavaScript rules 17 | 18 | [Why Auth0?](https://auth0.com/why-auth0) 19 | 20 | ## Create a free account in Auth0 21 | 22 | 1. Go to [Auth0](https://auth0.com) and click Sign Up. 23 | 2. Use Google, GitHub or Microsoft Account to login. 24 | 25 | ## Issue Reporting 26 | 27 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 28 | 29 | ## License 30 | 31 | This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info. 32 | -------------------------------------------------------------------------------- /01-Login/public/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "proxima-nova", sans-serif; 3 | text-align: center; 4 | font-size: 300%; 5 | font-weight: 100; 6 | } 7 | pre { 8 | text-align: left; 9 | } 10 | input[type=checkbox], 11 | input[type=radio] { 12 | position: absolute; 13 | opacity: 0; 14 | } 15 | input[type=checkbox] + label, 16 | input[type=radio] + label { 17 | display: inline-block; 18 | } 19 | input[type=checkbox] + label:before, 20 | input[type=radio] + label:before { 21 | content: ""; 22 | display: inline-block; 23 | vertical-align: -0.2em; 24 | width: 1em; 25 | height: 1em; 26 | border: 0.15em solid #0074d9; 27 | border-radius: 0.2em; 28 | margin-right: 0.3em; 29 | background-color: white; 30 | } 31 | input[type=radio] + label:before { 32 | border-radius: 50%; 33 | } 34 | input[type=radio]:checked + label:before, 35 | input[type=checkbox]:checked + label:before { 36 | background-color: #0074d9; 37 | box-shadow: inset 0 0 0 0.15em white; 38 | } 39 | input[type=radio]:focus + label:before, 40 | input[type=checkbox]:focus + label:before { 41 | outline: 0; 42 | } 43 | .btn { 44 | font-size: 140%; 45 | text-transform: uppercase; 46 | letter-spacing: 1px; 47 | border: 0; 48 | background-color: #16214D; 49 | color: white; 50 | } 51 | .btn:hover { 52 | background-color: #44C7F4; 53 | } 54 | .btn:focus { 55 | outline: none !important; 56 | } 57 | .btn.btn-lg { 58 | padding: 20px 30px; 59 | } 60 | .btn:disabled { 61 | background-color: #333; 62 | color: #666; 63 | } 64 | h1, 65 | h2, 66 | h3 { 67 | font-weight: 100; 68 | } 69 | #logo img { 70 | width: 300px; 71 | margin-bottom: 60px; 72 | } 73 | .home-description { 74 | font-weight: 100; 75 | margin: 100px 0; 76 | } 77 | h2 { 78 | margin-top: 30px; 79 | margin-bottom: 40px; 80 | font-size: 200%; 81 | } 82 | label { 83 | font-size: 100%; 84 | font-weight: 300; 85 | } 86 | .btn-next { 87 | margin-top: 30px; 88 | } 89 | .answer { 90 | width: 70%; 91 | margin: auto; 92 | text-align: left; 93 | padding-left: 10%; 94 | margin-bottom: 20px; 95 | } 96 | .login-page .login-box { 97 | padding: 100px 0; 98 | } 99 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Common logic 2 | defaults: &defaults 3 | steps: 4 | - attach_workspace: 5 | at: ~/ 6 | - run: 7 | name: Replace Auth0 test credentials 8 | command: | 9 | mv $AUTH0_CFG.example $AUTH0_CFG 10 | sed -i 's/{CLIENT_ID}/'$AUTH0_TEST_CLIENT_ID'/g' $AUTH0_CFG 11 | sed -i 's/{DOMAIN}/'$AUTH0_TEST_DOMAIN'/g' $AUTH0_CFG 12 | sed -i 's/{CLIENT_SECRET}/'$AUTH0_TEST_CLIENT_SECRET'/g' $AUTH0_CFG 13 | - run: 14 | name: Build pull request 15 | command: | 16 | docker build -t $CIRCLE_JOB ./$SAMPLE_PATH 17 | docker run -d -p 3000:3000 --name $CIRCLE_SHA1 --env-file ./$AUTH0_CFG $CIRCLE_JOB 18 | background: true 19 | - run: 20 | name: Wait for app to be available 21 | command: | 22 | sleep 20 23 | docker run --network host --rm appropriate/curl --retry 8 --retry-connrefused -v localhost:3000 24 | - run: 25 | name: Run tests 26 | command: | 27 | docker create --network host --name tester codeception/codeceptjs codeceptjs run-multiple --all --steps 28 | docker cp $(pwd)/lock_login_test.js tester:/tests/lock_login_test.js 29 | docker cp $(pwd)/codecept.conf.js tester:/tests/codecept.conf.js 30 | docker start -i tester 31 | working_directory: scripts 32 | - run: 33 | name: Copy app container logs 34 | command: | 35 | mkdir -p /tmp/out 36 | docker logs $CIRCLE_SHA1 > /tmp/out/app_logs.log 37 | docker cp tester:/tests/out /tmp/ 38 | when: on_fail 39 | - store_artifacts: 40 | path: /tmp/out 41 | 42 | # Jobs and Workflows 43 | version: 2 44 | jobs: 45 | checkout: 46 | machine: true 47 | steps: 48 | - checkout 49 | - run: git clone https://github.com/auth0-samples/spa-quickstarts-tests scripts 50 | - persist_to_workspace: 51 | root: ~/ 52 | paths: 53 | - project 54 | - scripts 55 | 01-login: 56 | machine: true 57 | environment: 58 | - AUTH0_CFG: 01-Login/.env 59 | - SAMPLE_PATH: 01-Login 60 | <<: *defaults 61 | 62 | workflows: 63 | version: 2 64 | quickstarts_login: 65 | jobs: 66 | - checkout: 67 | context: Quickstart Web App Test 68 | - 01-login: 69 | context: Quickstart Web App Test 70 | requires: 71 | - checkout 72 | -------------------------------------------------------------------------------- /01-Login/README.md: -------------------------------------------------------------------------------- 1 | # Auth0 Python Web App Sample 2 | 3 | This sample demonstrates how to add authentication to a Python web app using Auth0. 4 | 5 | # Running the App 6 | 7 | To run the sample, make sure you have `python` and `pip` installed. 8 | 9 | Rename `.env.example` to `.env` and populate it with the client ID, domain, secret, callback URL and audience for your 10 | Auth0 app. If you are not implementing any API you can use `https://YOUR_DOMAIN.auth0.com/userinfo` as the audience. 11 | Also, add the callback URL to the settings section of your Auth0 client. 12 | 13 | Register `http://localhost:3000/callback` as `Allowed Callback URLs` and `http://localhost:3000` 14 | as `Allowed Logout URLs` in your client settings. 15 | 16 | Run `pip install -r requirements.txt` to install the dependencies and run `python server.py`. 17 | The app will be served at [http://localhost:3000/](http://localhost:3000/). 18 | 19 | # Running the App with Docker 20 | 21 | To run the sample, make sure you have `docker` installed. 22 | 23 | To run the sample with [Docker](https://www.docker.com/), make sure you have `docker` installed. 24 | 25 | Rename the .env.example file to .env, change the environment variables, and register the URLs as explained [previously](#running-the-app). 26 | 27 | Run `sh exec.sh` to build and run the docker image in Linux or run `.\exec.ps1` to build 28 | and run the docker image on Windows. 29 | 30 | ## What is Auth0? 31 | 32 | Auth0 helps you to: 33 | 34 | * Add authentication with [multiple authentication sources](https://auth0.com/docs/identityproviders), 35 | either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, among others**,or 36 | enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 37 | * Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 38 | * Add support for **[linking different user accounts](https://auth0.com/docs/link-accounts)** with the same user. 39 | * Support for generating signed [JSON Web Tokens](https://auth0.com/docs/jwt) to call your APIs and 40 | **flow the user identity** securely. 41 | * Analytics of how, when and where users are logging in. 42 | * Pull data from other sources and add it to the user profile, through [JavaScript rules](https://auth0.com/docs/rules). 43 | 44 | ## Create a free account in Auth0 45 | 46 | 1. Go to [Auth0](https://auth0.com) and click Sign Up. 47 | 2. Use Google, GitHub or Microsoft Account to login. 48 | 49 | ## Issue Reporting 50 | 51 | If you have found a bug or if you have a feature request, please report them at this repository issues section. 52 | Please do not report security vulnerabilities on the public GitHub issue tracker. 53 | The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 54 | 55 | ## Author 56 | 57 | [Auth0](https://auth0.com) 58 | 59 | ## License 60 | 61 | This project is licensed under the MIT license. See the [LICENSE](LICENCE) file for more info. 62 | -------------------------------------------------------------------------------- /01-Login/server.py: -------------------------------------------------------------------------------- 1 | """Python Flask WebApp Auth0 integration example 2 | """ 3 | from functools import wraps 4 | import json 5 | from os import environ as env 6 | from werkzeug.exceptions import HTTPException 7 | 8 | from dotenv import load_dotenv, find_dotenv 9 | from flask import Flask 10 | from flask import jsonify 11 | from flask import redirect 12 | from flask import render_template 13 | from flask import session 14 | from flask import url_for 15 | from authlib.integrations.flask_client import OAuth 16 | from six.moves.urllib.parse import urlencode 17 | 18 | import constants 19 | 20 | ENV_FILE = find_dotenv() 21 | if ENV_FILE: 22 | load_dotenv(ENV_FILE) 23 | 24 | AUTH0_CALLBACK_URL = env.get(constants.AUTH0_CALLBACK_URL) 25 | AUTH0_CLIENT_ID = env.get(constants.AUTH0_CLIENT_ID) 26 | AUTH0_CLIENT_SECRET = env.get(constants.AUTH0_CLIENT_SECRET) 27 | AUTH0_DOMAIN = env.get(constants.AUTH0_DOMAIN) 28 | AUTH0_BASE_URL = 'https://' + AUTH0_DOMAIN 29 | AUTH0_AUDIENCE = env.get(constants.AUTH0_AUDIENCE) 30 | 31 | app = Flask(__name__, static_url_path='/public', static_folder='./public') 32 | app.secret_key = constants.SECRET_KEY 33 | app.debug = True 34 | 35 | 36 | @app.errorhandler(Exception) 37 | def handle_auth_error(ex): 38 | response = jsonify(message=str(ex)) 39 | response.status_code = (ex.code if isinstance(ex, HTTPException) else 500) 40 | return response 41 | 42 | 43 | oauth = OAuth(app) 44 | 45 | auth0 = oauth.register( 46 | 'auth0', 47 | client_id=AUTH0_CLIENT_ID, 48 | client_secret=AUTH0_CLIENT_SECRET, 49 | api_base_url=AUTH0_BASE_URL, 50 | access_token_url=AUTH0_BASE_URL + '/oauth/token', 51 | authorize_url=AUTH0_BASE_URL + '/authorize', 52 | client_kwargs={ 53 | 'scope': 'openid profile email', 54 | }, 55 | ) 56 | 57 | 58 | def requires_auth(f): 59 | @wraps(f) 60 | def decorated(*args, **kwargs): 61 | if constants.PROFILE_KEY not in session: 62 | return redirect('/login') 63 | return f(*args, **kwargs) 64 | 65 | return decorated 66 | 67 | 68 | # Controllers API 69 | @app.route('/') 70 | def home(): 71 | return render_template('home.html') 72 | 73 | 74 | @app.route('/callback') 75 | def callback_handling(): 76 | auth0.authorize_access_token() 77 | resp = auth0.get('userinfo') 78 | userinfo = resp.json() 79 | 80 | session[constants.JWT_PAYLOAD] = userinfo 81 | session[constants.PROFILE_KEY] = { 82 | 'user_id': userinfo['sub'], 83 | 'name': userinfo['name'], 84 | 'picture': userinfo['picture'] 85 | } 86 | return redirect('/dashboard') 87 | 88 | 89 | @app.route('/login') 90 | def login(): 91 | return auth0.authorize_redirect(redirect_uri=AUTH0_CALLBACK_URL, audience=AUTH0_AUDIENCE) 92 | 93 | 94 | @app.route('/logout') 95 | def logout(): 96 | session.clear() 97 | params = {'returnTo': url_for('home', _external=True), 'client_id': AUTH0_CLIENT_ID} 98 | return redirect(auth0.api_base_url + '/v2/logout?' + urlencode(params)) 99 | 100 | 101 | @app.route('/dashboard') 102 | @requires_auth 103 | def dashboard(): 104 | return render_template('dashboard.html', 105 | userinfo=session[constants.PROFILE_KEY], 106 | userinfo_pretty=json.dumps(session[constants.JWT_PAYLOAD], indent=4)) 107 | 108 | 109 | if __name__ == "__main__": 110 | app.run(host='0.0.0.0', port=env.get('PORT', 3000)) 111 | --------------------------------------------------------------------------------