Search code examples
.netreactjsreact-routeridentityserver4react-router-dom

How to fix routing for IdentityServer ReactJS


I'm setting up an identity authentication for a project im currently working on. I need to be able to push a button to log into my server and then be redirected to IdentityServer4 and back again to my application.

I'm using "react-router-dom": "^4.3.1", "redux-oidc": "^3.1.4", "oidc-client": "^1.8.2",

And the projects backend is set up using .NET. I've taken the https://github.com/maxmantz/redux-oidc-example example to start my implementation and used http://docs.identityserver.io/en/aspnetcore1/quickstarts/7_javascript_client.html first to make it so that the backend and API worked.

My problem is pretty much the same as https://github.com/maxmantz/redux-oidc/issues/96 but I'm not understanding how to solve it.

I've tried solving it with different links I've found but they all keep going back to the same issue. I think thats because of the routing like mentioned earlier.

FrontEnd:

App and index:

const App = () => (
  <BrowserRouter>
    <Routes />
  </BrowserRouter>
);

ReactDOM.render(
  <Provider store={store}>
    <OidcProvider store={store} userManager={userManager}>
       <App />
    </OidcProvider>
  </Provider>,
  document.getElementById('root')
);

Router:

const Routes = props => {
  return (
    <div className="App">
      {console.log('Routes props, ',  props)}
      <Route path="/" component={Header} />
      <Switch>
        <Route path="/home" component={HomePage} />
        <Route path="/" component={LandingPage} />
        {/* I THINK MY ERROR LIES HERE, I COULD USE WHAT EVER PATH WITHOUT IT MEANING ANYTHING*/ }
        <Route path="/callback" component={CallbackPage} />
      </Switch>
    </div>
  );
};

function mapStateToProps(state) {
  return {
    user: state.oidc.user,
    isLoadingUser: state.oidc.isLoadingUser
  };
}

function mapDispatchToProps(dispatch) {
  return {
    dispatch
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Routes);

authConst:

import { createUserManager } from 'redux-oidc';

const userManagerConfig= {
  authority: 'http://localhost:5000',
  client_id: 'js',
  redirect_uri: 'http://localhost:3000/callback',
  response_type: 'code',
  scope: 'openid profile api1',
  post_logout_redirect_uri: 'http://localhost:3000'
};

const userManager = createUserManager(userManagerConfig);
export default userManager;

LoginPage:

import React from 'react';
import userManager from '../../setup/authConst';


class LoginPage extends React.Component {
  onLoginButtonClick = () => {
    userManager.signinRedirect();
};

  render() {
    return (
      <div style={styles.root}>
        <h3>Welcome to the redux-oidc sample app!</h3>
        <p>Please log in to continue</p>
        <button onClick={this.onLoginButtonClick}>Redirect Login</button>
      </div>
    );
  }
}
export default LoginPage;

LandingPage:

import { connect } from 'react-redux';
import LoginPage from './LoginPage';
import { Redirect } from 'react-router-dom';

function LandingPage(props) {
  const { user } = props;
  return !user || user.expired ? (
    <LoginPage />
  ) : (
    <HomePage />
  );
}

function mapStateToProps(state) {
  return {
    user: state.oidc.user
  };
}

function mapDispatchToProps(dispatch) {
  return {
    dispatch
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LandingPage);

Callback: Never touched. No console.log will be printed

import React from 'react';
import { connect } from 'react-redux';
import { CallbackComponent } from 'redux-oidc';
import { push } from 'react-router-redux';

class CallbackPage extends React.Component {
  successCallback = user => {
    this.props.dispatch(push('/'));
  };
  errorCallback = error => {
    console.error(
      'There was an error handling the token callback: ' + error.message
    );
  };

  render() {
    // just redirect to '/' in both cases
    return (
      <>
        <CallbackComponent successCallback={this.successCallback}>
          <div>Redirecting...</div>
        </CallbackComponent>
      </>
    );
  }
}

export default connect()(CallbackPage);

store:

import thunkMiddleware from 'redux-thunk';
//import loggerMiddleware from 'redux-logger';
import rootReducer from '../reducers/rootReducer';
import { applyMiddleware, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { loadUser } from "redux-oidc";
import userManager from './authConst'

function configureStore(preloadedState) {
  const middlewares = [thunkMiddleware];
  const middlewareEnhancer = applyMiddleware(...middlewares);
  const enhancers = [middlewareEnhancer];
  const composedEnhancers = composeWithDevTools(...enhancers);

  /*if (process.env.NODE_ENV !== 'production' && module.hot) {
        module.hot.accept('./reducers', () => store.replaceReducer(rootReducer))
    }*/


  return createStore(rootReducer, preloadedState, composedEnhancers);
}

const store = configureStore(); 

loadUser(store, userManager)
  .then((user) => {
    console.log('USER_FOUND', user);
    if (user) {
      store.dispatch({
        type: 'redux-oidc/USER_FOUND',
        payload: user,
      });
    }
  }).catch((err) => {
    console.log(err);
  });

export default store; 

Backend:

 new Client
                {
                    ClientId = "js",
                    ClientName = "JavaScript Client",
                    AllowedGrantTypes = GrantTypes.Code,

                    RedirectUris =     { "http://localhost:3000/callback" },
                    PostLogoutRedirectUris = { "http://localhost:3000" },
                    AllowedCorsOrigins =     { "http://localhost:3000" },

                    AllowedScopes =
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api1"
                    }

expected to be redirected to the CallbackPage, but never gets there.

example of my URI after loginbutton: http://localhost:3000/call?code=415d7281052e165e5636cbc421b058a963c886ae73c6a8fe52ce65e1e384960e&scope=openid%20profile%20api1&state=c903848b038e4f0a83a1cb402804d868&session_state=wjishlP7ceWS0jpgWoHU9dkTKnef_BB1iSQFIh6QcJY.97b10e0098da117feb2a7a043fda362b


Solution

  • Just moved my Route for landing page beneath callback and it works.