Skip to content

Commit

Permalink
YDA-5491: implement OIDC anti-forgery state token
Browse files Browse the repository at this point in the history
  • Loading branch information
lwesterhof committed Oct 18, 2023
1 parent e846062 commit a2dc04e
Showing 1 changed file with 20 additions and 2 deletions.
22 changes: 20 additions & 2 deletions user/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import json
import re
import secrets
from typing import List

import jwt
Expand Down Expand Up @@ -211,6 +212,9 @@ def userinfo_request(token: str) -> requests.Response:

return response

class StateMismatchError(Exception):
pass

class UserinfoSubMismatchError(Exception):
pass

Expand All @@ -222,6 +226,13 @@ class UserinfoEmailMismatchError(Exception):
exception_occurred = "OPENID_ERROR" # To identify exception in finally-clause

try:
email = g.login_username.lower()

# Ensure that the request is not a forgery and that the user sending
# this connect request is the expected user.
if request.args['state'] != session.get('state'):
raise StateMismatchError

token_response = token_request()
js = token_response.json()
access_token = js['access_token']
Expand Down Expand Up @@ -251,8 +262,6 @@ class UserinfoEmailMismatchError(Exception):

# Check if login email matches with user info email.
email_identifier = app.config.get('OIDC_EMAIL_FIELD')
email = g.login_username.lower()

userinfo_email = userinfo_payload[email_identifier]
if not isinstance(userinfo_email, list):
userinfo_email = [userinfo_email]
Expand Down Expand Up @@ -313,6 +322,10 @@ class UserinfoEmailMismatchError(Exception):
True
)

except StateMismatchError:
# Invalid state parameter.
log_error("Invalid state parameter")

except UserinfoSubMismatchError:
# Possible Token substitution attack.
log_error(
Expand Down Expand Up @@ -379,6 +392,11 @@ def should_redirect_to_oidc(username: str) -> bool:
def oidc_authorize_url(username: str) -> str:
authorize_url: str = app.config.get('OIDC_AUTH_URI')

# Generate a random string for the state parameter.
# https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
session['state'] = secrets.token_urlsafe(32)
authorize_url += '&state=' + session['state']

if app.config.get('OIDC_LOGIN_HINT') and username:
authorize_url += '&login_hint=' + username

Expand Down

0 comments on commit a2dc04e

Please sign in to comment.