Skip to content

Instantly share code, notes, and snippets.

@hteo1337
Forked from gchamon/backend.py
Created December 29, 2022 12:09
Show Gist options
  • Select an option

  • Save hteo1337/226014cb854ba624cc8006012b539459 to your computer and use it in GitHub Desktop.

Select an option

Save hteo1337/226014cb854ba624cc8006012b539459 to your computer and use it in GitHub Desktop.
Gists with functional code from papyrus article about OIDC, JWT and Python
from flask import Flask
from uuid import uuid4
app = Flask(__name__)
app.config["SECRET_KEY"] = str(uuid4())
IDP_CONFIG = {
"well_known_url": "Identity Provider wellknown url: https://{TENANT}.auth0.com/.well-known/openid-configuration",
"client_id": "Your app client ID",
"client_secret": "Your app client secret",
"scope": ["profile", "email", "openid"]
}
import requests
from flask import url_for
from requests_oauthlib import OAuth2Session
def get_well_known_metadata():
response = requests.get(IDP_CONFIG["well_known_url"])
response.raise_for_status()
return response.json()
def get_oauth2_session(**kwargs):
oauth2_session = OAuth2Session(IDP_CONFIG["client_id"],
scope=IDP_CONFIG["scope"],
redirect_uri=url_for(".callback", _external=True),
**kwargs)
return oauth2_session
from flask import redirect, session
@app.route("/login")
def login():
well_known_metadata = get_well_known_metadata()
oauth2_session = get_oauth2_session()
authorization_url, state = oauth2_session.authorization_url(well_known_metadata["authorization_endpoint"])
session["oauth_state"] = state
return redirect(authorization_url)
from flask import request
@app.route("/callback")
def callback():
well_known_metadata = get_well_known_metadata()
oauth2_session = get_oauth2_session(state=session["oauth_state"])
session["oauth_token"] = oauth2_session.fetch_token(well_known_metadata["token_endpoint"],
client_secret=IDP_CONFIG["client_secret"],
code=request.args["code"])["id_token"]
return "ok"
@app.route("/user/token")
def get_user_token():
return session["oauth_token"]
import jwt
from jwt import PyJWKClient
from jwt.exceptions import DecodeError
from werkzeug.exceptions import InternalServerError, Unauthorized
def get_jwks_client():
well_known_metadata = get_well_known_metadata()
jwks_client = PyJWKClient(well_known_metadata["jwks_uri"])
return jwks_client
jwks_client = get_jwks_client()
@app.before_request
def verify_and_decode_token():
if request.endpoint not in {"login", "callback"}:
if "Authorization" in request.headers:
token = request.headers["Authorization"].split()[1]
elif "oauth_token" in session:
token = session["oauth_token"]
else:
return Unauthorized("Missing authorization token")
try:
signing_key = jwks_client.get_signing_key_from_jwt(token)
header_data = jwt.get_unverified_header(token)
request.user_data = jwt.decode(token,
signing_key.key,
algorithms=[header_data['alg']],
audience=IDP_CONFIG["client_id"])
except DecodeError:
return Unauthorized("Authorization token is invalid")
except Exception:
return InternalServerError("Error authenticating client")
@app.route("/user/id")
def get_user_id():
return request.user_data["email"]
if __name__ == "__main__":
app.run()
from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
chrome_options = ChromeOptions()
chrome_options.add_argument("--user-data-dir=chrome-data")
chrome_options.add_argument("--app=http://localhost:5000/login")
driver = webdriver.Chrome(options=chrome_options)
WebDriverWait(driver, 300).until(
EC.visibility_of_element_located((By.XPATH, "//*[contains(text(), 'ok')]")))
chromium_cookies = driver.get_cookies()
driver.close()
requests_cookies = {c["name"]: c["value"] for c in chromium_cookies}
import requests
token_response = requests.get("http://localhost:5000/user/token", cookies=requests_cookies)
token_response.raise_for_status()
token = token_response.text
userid_response = requests.get("http://localhost:5000/user/id", headers={"Authorization": f"Bearer {token}"})
userid_response.raise_for_status()
print(userid_response.text)
flask==2.0.2
requests-oauthlib==1.3.0
requests==2.26.0
pyjwt[crypto]==2.3.0
selenium==4.1.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment