0

I have a React UI. I need to implement Okta Web app, with server-side authentication. The server I am using is Python. Unable to fix the issue with Okta giving this error: 'AuthSdkError: Unable to retrieve OAuth redirect params from storage'

From looking at my debugging logs, cookie data all seems valid and present.

Python:

@app.route("/login")
def login():
    session['app_state'] = secrets.token_urlsafe(64)
    session['code_verifier'] = secrets.token_urlsafe(64)

    # Debugging: Print session data
    print("Session before redirect:", dict(session))

    hashed = hashlib.sha256(session['code_verifier'].encode('ascii')).digest()
    encoded = base64.urlsafe_b64encode(hashed)
    code_challenge = encoded.decode('ascii').strip('=')

    query_params = {
        'client_id': os.environ['CLIENT_ID'],
        'redirect_uri': "http://localhost:5000/login/callback",
        'scope': "openid email profile",
        'state': session['app_state'],
        'code_challenge': code_challenge,
        'code_challenge_method': 'S256',
        'response_type': 'code',
        'response_mode': 'query'
    }

    request_uri = "{base_url}?{query_params}".format(
        base_url=os.environ['ORG_URL'] + "oauth2/default/v1/authorize",
        query_params=requests.compat.urlencode(query_params)
    )

    print("Redirecting to: ", request_uri)
    return redirect(request_uri)

@app.route("/login/callback")
def callback():
    
    print("Session in callback before checking state:", dict(session))
    
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    code = request.args.get("code")
    app_state = request.args.get("state")

    # Debugging: Print session data and received state
    print("Callback session data: ", dict(session))
    print(f"Received state: {app_state}")
    print(f"Expected state: {session.get('app_state')}")
    print(f"Received code: {code}")

    if app_state != session.get('app_state'):
        print(f"App state mismatch: expected {session.get('app_state')} but got {app_state}")
        return "The app state does not match", 400
    if not code:
        return "The code was not returned or is not accessible", 403

    query_params = {
        'grant_type': 'authorization_code',
        'code': code,
        'redirect_uri': request.base_url,
        'code_verifier': session['code_verifier']
    }
    query_params = requests.compat.urlencode(query_params)
    exchange = requests.post(
        os.environ['ORG_URL'] + "oauth2/default/v1/token",
        headers=headers,
        data=query_params,
        auth=(os.environ['CLIENT_ID'], os.environ['CLIENT_SECRET']),
    ).json()

    # Debugging: Print token exchange response
    print("Token exchange response: ", exchange)

    if not exchange.get("token_type"):
        return "Unsupported token type. Should be 'Bearer'.", 403
    access_token = exchange["access_token"]
    id_token = exchange["id_token"]

    userinfo_response = requests.get(os.environ['ORG_URL'] + "oauth2/default/v1/userinfo",
                                     headers={'Authorization': f'Bearer {access_token}'}).json()

    unique_id = userinfo_response["sub"]
    user_email = userinfo_response["email"]
    user_name = userinfo_response["given_name"]

    user = User(
        id_=unique_id, name=user_name, email=user_email
    )

    if not User.get(unique_id):
        User.create(unique_id, user_name, user_email)

    login_user(user)

    # Clean up session
    session.pop('app_state', None)
    session.pop('code_verifier', None)

    return send_from_directory(app.static_folder, 'index.html')

React app.js

const oktaAuth = new OktaAuth({
  issuer: 'https://dev-xxxxxxxxx.okta.com/oauth2/default',
  clientId: 'xxxxxxxxxxxxxx',
  redirectUri: window.location.origin + '/login/callback'
});

const App = () => {
  const history = useHistory();

  const restoreOriginalUri = async (_oktaAuth, originalUri) => {
    history.replace(toRelativeUrl(originalUri || '/', window.location.origin));
  };

  return (
    <Security oktaAuth={oktaAuth} restoreOriginalUri={restoreOriginalUri}>
      <Switch>
        <Route path="/" exact component={Home} />
        <Route path="/login/callback" component={LoginCallback} />
      </Switch>
    </Security>
  );
};

const RouterApp = () => (
  <Router>
    <App />
  </Router>
);

export default RouterApp;

0