maxmantz/redux-oidc

Callback/ access is forbidden in built application

rralbritton opened this issue · 3 comments

I have been using redux-oidc with all my apps lately and its always worked great. I just updated and started using react 16.8 (instead of 16.4) , redux 4.04, and react-redux 5.1.1.
I have springboot as my backend application.
Everything works as expected when I run the app locally, but once I build and deploy it the callback is coming back as forbidden (response 403), and I can not figure out why. Everything looks to be in order.

import { createUserManager } from 'redux-oidc';

let host = window.location.host;
let userManagerConfig = {};

 userManagerConfig = {
        authority: "https://login.dts.utah.gov:443/sso/oauth2",
        client_id: "misdrive-hydatopneumatolytic-076996",
        redirect_uri: "https://" + host + "/callback",
        response_type: "token id_token",
        scope: "openid email",
        post_logout_redirect_uri: "https://" + host + "/",
        loadUserInfo: true,
        filterProtocolClaims: true
    }
const userManager = createUserManager(userManagerConfig);
export default userManager;

CALLBACK:

import React from "react";
import { connect } from "react-redux";
import { CallbackComponent } from "redux-oidc";
import userManager from "./Authorization";
import history from "../components/common/History";
import spinner from "../images/loading_spinner.gif";
import setJWTToken from './setJWTToken';

class LoginCallback extends React.Component { 

    successCallback = () => {
        if (sessionStorage.length > 0) {
            let token = JSON.parse(sessionStorage.getItem("oidc.user:" + userManager._settings._authority + ":" + userManager._settings._client_id)).access_token;
           alert("SuccessCallback: ", token);
            setJWTToken(token);
            history.push("/searchhb357");
        } 
    };

    render() {
        alert("in /callback render");

        return (
            <CallbackComponent
                userManager={userManager}
                successCallback={this.successCallback}
                errorCallback={error => {
                   alert("ERROR: ", error);
                    history.push("/");
                }}
            >
                <div><img src={spinner} className="spinner" id="spinner" alt="spinner" /></div>
            </CallbackComponent>
        );
    }
}

export default connect()(LoginCallback);

My redurects and post logout registered with my oidc provider:

image

My authorization request is successful - and you can see the the query parms below - that the callback matches my code
image

But then it does the call back to
https://hb357-at.deq.utah.gov/callback
And returns a 403

here's my app.js as well

import React from 'react';
import { Provider } from "react-redux";
import store from "../store/store";
import { Router, Route, Switch } from "react-router-dom";
import Header from "./common/Header";
import Footer from "./common/Footer";
import history from "./common/History";
import HB357SearchTable from '../hb357/HB357SearchTable';
import HB357Form from '../hb357/HB357Form';

/*Security*/
import handleLogout from '../authorization/handleLogout';
import LoginPage from './login/LoginPage';
import userManager from "../authorization/Authorization";
import LoginCallback from '../authorization/LoginCallback';
import { OidcProvider } from 'redux-oidc';
import setJWTToken from '../authorization/setJWTToken';

/*CSS*/
import "./App.css";

/*Grab the security token generated by login and include it in header for all requests*/
if (sessionStorage.length > 0) {
  let currentTime = Date.now() / 1000;
  let token = JSON.parse(sessionStorage.getItem("oidc.user:" + userManager._settings._authority + ":" + userManager._settings._client_id)).access_token;
  let expired = JSON.parse(sessionStorage.getItem("oidc.user:" + userManager._settings._authority + ":" + userManager._settings._client_id)).expires_at;
  if (expired < currentTime) {
    handleLogout()
  }
  else {
    setJWTToken(token);
  }
}

const Page404 = ({ location }) => (
  <div>
    <h2>404 ERROR: <code>{location.pathname}</code> is not a valid URL</h2>
  </div>
);

function App() {
  return (
    <Provider store={store}>
      <OidcProvider store={store} userManager={userManager}>
        <Router history={history}>
          <div>
            <Header />
            <div className="container-fluid">
              <Switch>
                <Route exact path="/" component={LoginPage} />
                <Route exact path="/callback" render={props => <LoginCallback {...props} />} />
                <Route exact path="/searchhb357" render={props => <HB357SearchTable {...props} />} />
                <Route exact path="/hb357surveyresponse/:responseId" render={props => <HB357Form {...props} />} />

                <Route component={Page404} />

              </Switch>
            </div>
            <Footer />
          </div>
        </Router>
      </OidcProvider>
    </Provider>
  );
}

export default App;

I'm not seeing anything in the docs to suggest wy this wouldn't cont to work for me - is there some kind of conflict between versions here?

I have found a solution - React 16.8 does not register the serviceworker by default. Once I change serviceworker.unregister() to serviceworker.register() in index.js everything started working. Is this expected behavior?

Everything looks fine from the React point of view. The fact that on your local machine everything works fine adds to that notion. My guess is that the webserver your app is hosted on forbids this routing. Since it is a virtual route, some webservers need special configuration to correctly navigate around SPAs,

In addition there is no token sent back in the URL when /callback is requested. Usually the token is transmitted via a query parameter such as client_id in the /authorize request. Are you sure the authentication went okay? Have you upgraded your backend token server as well?

@rralbritton you were a little quicker than me there 👍

No I don't see why the service worker would intervene with the functionality of this library.