Created
February 14, 2020 02:53
-
-
Save brianv0/9609748b8b77daf6d974598f5dee197c to your computer and use it in GitHub Desktop.
Prepare session for Redis
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Inject a session oauth2_proxy redis session store | |
import base64 | |
import hashlib | |
import json | |
import os | |
from cryptography.hazmat.backends import default_backend | |
from cryptography.hazmat.primitives import serialization | |
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes | |
def encrypt_field(field: str, oauth2_secret: str) -> bytes: | |
secret_key_encoded = oauth2_secret | |
secret_key = base64.urlsafe_b64decode(secret_key_encoded) | |
backend = default_backend() | |
iv = os.urandom(16) | |
cipher = Cipher(algorithms.AES(secret_key), modes.CFB(iv), backend=backend) | |
encryptor = cipher.encryptor() | |
cipher_text: bytes = encryptor.update(field.encode("utf-8")) + encryptor.finalize() | |
encrypted_field = iv + cipher_text | |
return base64.b64encode(encrypted_field) | |
def prepare_session(prefix: str, oauth2_secret: str, token: str, email: str) -> Tuple[str, bytes]: | |
# prepare ticket and ticket secret | |
ticket_id = hashlib.sha1(os.urandom(16)).hexdigest() | |
secret = os.urandom(16) | |
secret_b64 = base64.urlsafe_b64encode(secret).decode().rstrip("=") | |
ticket = f"{prefix}-{ticket_id}.{secret_b64}" | |
# serialize session | |
session_obj = { | |
"IDToken": encrypt_field(token, oauth2_secret).decode(), | |
"Email": encrypt_field(email, oauth2_secret).decode(), | |
"User": encrypt_field(email, oauth2_secret).decode(), | |
"CreatedAt": "2020-01-01T06:00:00Z", | |
"ExpiresOn": "2020-01-01T07:00:00Z", | |
} | |
session_payload_str = json.dumps(session_obj) | |
# encrypt session | |
backend = default_backend() | |
cipher = Cipher(algorithms.AES(secret), modes.CFB(secret), backend=backend) | |
encryptor = cipher.encryptor() | |
encrypted_oauth2_session = encryptor.update(session_payload_str.encode()) + encryptor.finalize() | |
# return ticket and encrypted session | |
return ticket, encrypted_oauth2_session | |
ticket, encrypted_session = prepare_session( | |
"_oauth2_proxy", # OAUTH2_PROXY_COOKIE_NAME | |
"w8SfzQKjoE4Jfrdn9yggaVd2hf9OIwzl", # OAUTH2_PROXY_COOKIE_SECRET | |
"eyJ...(id token)", # ID token | |
"[email protected]", # Email from ID token | |
) | |
handle = ticket.split(".")[0] | |
# SETEX <handle> 3600 <encrypted_session> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When oauth2_proxy is configured with
--skip-jwt-bearer-tokens
, you can also specify--skip-session-tickets
and use a session ticket in place of a full JWT. This can be usefulfor APIs when JWTs are large.
A user could get a ticket in two ways: a ticket can be extracted from a cookie, or
a ticket and session can be constructed from a JWT and injected into the redis store,
if you have the oauth2_proxy cookie secret and cookie name.
This is an example of preparing a session object for storage in redis and returning
the ticket used to encrypt it.