Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect onLoad only if not authenticated with @azure/msal-react

I'm trying to adapt the sample project for my needs.

My needs are essentially:

  1. Automatically redirect login if the user is not authenticated when they navigate to the root route...
  2. If they are, load the protected child components.

I have step 1. working as expected. However, after they have been signed in it seems like it is trying to reroute again and I get:

interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors

  70 | 
  71 | useEffect(() => {
  72 |   if (!isAuthenticated) {
> 73 |     msalInstance.loginRedirect(loginRequest);
     | ^  74 |   }
  75 | })
  76 | 

It does this whether or not there is the !isAuthenticated conditional.

The usage of the useIsAuthenticated comes from this documentation and appears to evaluate to false even if the user is logged in already.

This is what I have thus far:

import { Configuration, RedirectRequest } from '@azure/msal-browser';

// Config object to be passed to Msal on creation
export const msalConfig: Configuration = {
  auth: {
    clientId: '<client_id>',
    authority: 'https://login.microsoftonline.com/<tenant_id>',
  },
};

// Add here scopes for id token to be used at MS Identity Platform endpoints.
export const loginRequest: RedirectRequest = {
  scopes: ['User.Read'],
};

// Add here the endpoints for MS Graph API services you would like to use.
export const graphConfig = {
  graphMeEndpoint: 'https://graph.microsoft.com/v1.0/me',
};

// index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import { PublicClientApplication } from '@azure/msal-browser';
import { msalConfig } from './components/authConfig';
import { MsalProvider } from '@azure/msal-react';

const msalInstance = new PublicClientApplication(msalConfig);

ReactDOM.render(
  <React.StrictMode>
    <MsalProvider instance={msalInstance}>
      <App />
    </MsalProvider>
  </React.StrictMode>,
  document.getElementById('root')
);
// App.tsx
import React, { useEffect } from 'react';
import {
  AuthenticatedTemplate,
  UnauthenticatedTemplate,
  useMsal,
  useIsAuthenticated,
} from '@azure/msal-react';
import { loginRequest } from './authConfig';

const App = () => {
  const isAuthenticated = useIsAuthenticated();
  const { instance } = useMsal();

  console.log(isAuthenticated);

  useEffect(() => {
    if (!isAuthenticated) {
      instance.loginRedirect(loginRequest);
    }
  });

  return (
    <div className='App'>
      <AuthenticatedTemplate>
        <div>Signed in...</div>
      </AuthenticatedTemplate>

      <UnauthenticatedTemplate>
        <div>Signing in...</div>
      </UnauthenticatedTemplate>
    </div>
  );
};

export default App;

Suggestions for how to resolve this?

like image 289
cjones Avatar asked Mar 01 '23 16:03

cjones


2 Answers

Ok, I was able to sort this out with some help:

const App = () => {
  const isAuthenticated = useIsAuthenticated();
  const { instance, inProgress } = useMsal();

  if (inProgress === InteractionStatus.None && !isAuthenticated) {
    instance.loginRedirect(loginRequest);
  }

  return (
    <div className='App'>
      <AuthenticatedTemplate>
        <div>Signed in...</div>
      </AuthenticatedTemplate>

      <UnauthenticatedTemplate>
        <div>Signing in...</div>
      </UnauthenticatedTemplate>
    </div>
  );
};

export default App;
like image 80
cjones Avatar answered Apr 26 '23 09:04

cjones


You can use simply MsalAuthenticationTemplate component instead of AuthenticatedTemplate/UnauthenticatedTemplate:

import React from "react";
import { MsalAuthenticationTemplate } from "@azure/msal-react";
import { InteractionType } from "@azure/msal-browser";

function ErrorComponent({error}) {
    return <p>An Error Occurred: {error}</p>;
}

function LoadingComponent() {
    return <p>Authentication in progress...</p>;
}

export function Example() {
    const authRequest = {
        scopes: ["openid", "profile"]
    };

    return (
        // authenticationRequest, errorComponent and loadingComponent props are optional
        <MsalAuthenticationTemplate 
            interactionType={InteractionType.Popup} 
            errorComponent={ErrorComponent} 
            loadingComponent={LoadingComponent}
        >
            <p>At least one account is signed in!</p>
        </MsalAuthenticationTemplate>
      )
};
like image 37
Ciccio Avatar answered Apr 26 '23 10:04

Ciccio