Setting up OIDC authentication in React with IdentityServer4 integration

I’m working on implementing authentication in my React app using IdentityServer4 and the oidc-client library. I’ve been following some documentation but I’m running into several issues.

My authentication component looks like this:

import React, { Component } from 'react';
import {authenticate, signOut, callService, display} from '../../authService'
import {Route, Link} from 'react-router';

export default class AuthComponent extends Component {
    constructor(props) {
      super(props);
    }

    render() {
      return (
        <div>
            <div>  
                <button id="signin" onClick={() => {authenticate()}}>Sign In</button>
                <button id="service" onClick={() => {callService()}}>Access Service</button>
                <button id="signout" onClick={() => {signOut()}}>Sign Out</button>

                <pre id="output"></pre>

            </div>  

            <div>
                <Route exact path="/auth-callback" render={() => {window.location.href="auth-callback.html"}} />
            </div>
        </div>
      );
    }
  }

And my auth service file:

import Oidc from 'oidc-client'

export function display() {
  document.getElementById('output').innerText = '';

  Array.prototype.forEach.call(arguments, function (message) {
      if (message instanceof Error) {
          message = "Error: " + message.message;
      }
      else if (typeof message !== 'string') {
          message = JSON.stringify(message, null, 2);
      }
      document.getElementById('output').innerHTML += message + '\r\n';
  });
}

var settings = {
  authority: "http://localhost:5000",
  client_id: "react_app",
  redirect_uri: "http://localhost:3000/auth-callback.html",
  response_type: "id_token token",
  scope:"openid profile myapi",
  post_logout_redirect_uri : "http://localhost:3000/index.html",
};
var manager = new Oidc.UserManager(settings);

manager.getUser().then(function (currentUser) {
  if (currentUser) {
      display("User is authenticated", currentUser.profile);
  }
  else {
      display("User is not authenticated");
  }
});

export function authenticate() {
  manager.signinRedirect();
}

export function callService() {
  manager.getUser().then(function (currentUser) {
      var endpoint = "http://localhost:5001/api/data";

      var request = new XMLHttpRequest();
      request.open("GET", endpoint);
      request.onload = function () {
          display(request.status, JSON.parse(request.responseText));
      }
      request.setRequestHeader("Authorization", "Bearer " + currentUser.access_token);
      request.send();
  });
}

export function signOut() {
  manager.signoutRedirect();
}

The main problems I’m facing are that after successful login the callback never gets processed properly, the user state doesn’t update, and the API calls fail because no token is found. I can see tokens in localStorage but they don’t seem to be accessible.

Any ideas on what I might be doing wrong? Is this the right approach for React and IdentityServer4 integration?

Your callback handling approach is problematic because you’re mixing React routing with static HTML files. The redirect to auth-callback.html bypasses React’s state management entirely, which explains why your user state never updates. I encountered similar issues when implementing OIDC in my React applications. Consider creating a dedicated callback component that handles manager.signinRedirectCallback() and then updates your application state accordingly. Additionally, your token retrieval might be failing because the callback processing never completes successfully. I recommend setting up proper error handling and logging in your auth service to see exactly where the flow breaks down. The localStorage tokens you’re seeing are likely incomplete or improperly processed due to the callback issue.

looks like your mixing spa routing with static files which is causing issues. try using manager.signinRedirectCallback() in your react component instead of redirecting to auth-callback.html. also make sure your identityserver client is configured for spa flows with pkce enabled - the implicit flow your using is kinda outdated now

hmm interesting setup there! are you handeling the callback properly in that auth-callback.html file? looks like your redirecting to a static html instead of processing it in react. also curious - have you checked your identityserver4 config for the client settings? sometimes the issue is on the server side rather than client