diff --git a/app/main/views/index.py b/app/main/views/index.py index ec489d5ac..012383f84 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -1,6 +1,15 @@ import os +import secrets -from flask import abort, current_app, redirect, render_template, request, url_for +from flask import ( + abort, + current_app, + redirect, + render_template, + request, + session, + url_for, +) from flask_login import current_user from app import status_api_client @@ -23,8 +32,12 @@ def index(): ) url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL") # handle unit tests + + nonce = secrets.token_urlsafe() + session["nonce"] = nonce + if url is not None: - url = url.replace("NONCE", token) + url = url.replace("NONCE", nonce) url = url.replace("STATE", token) return render_template( "views/signedout.html", diff --git a/app/main/views/sign_in.py b/app/main/views/sign_in.py index 5c1f03855..85ea1427b 100644 --- a/app/main/views/sign_in.py +++ b/app/main/views/sign_in.py @@ -1,5 +1,6 @@ import json import os +import secrets import time import uuid @@ -13,6 +14,7 @@ from flask import ( redirect, render_template, request, + session, url_for, ) from flask_login import current_user @@ -87,14 +89,11 @@ def _get_access_token(code, state): # pragma: no cover ) nonce = id_token["nonce"] - state = request.args.get("state") - - if nonce != state: - current_app.logger.warning(f"{nonce} != {state}") + saved_nonce = session.pop("nonce") + if nonce != saved_nonce: + current_app.logger.error(f"Nonce Error: {nonce} != {saved_nonce}") abort(403) - # redis_client.delete(redis_key) - try: access_token = response_json["access_token"] except KeyError as e: @@ -225,11 +224,15 @@ def sign_in(): # pragma: no cover current_app.config["DANGEROUS_SALT"], ) url = os.getenv("LOGIN_DOT_GOV_INITIAL_SIGNIN_URL") - state = request.args.get("state") + + nonce = secrets.token_urlsafe() + session["nonce"] = nonce + # handle unit tests if url is not None: - url = url.replace("NONCE", state) # We are getting the state back as the nonce. + url = url.replace("NONCE", nonce) url = url.replace("STATE", token) + return render_template( "views/signin.html", again=bool(redirect_url),