1
votes

I am fairly new to React and trying to implement Single Sign On Authentication in my React App.

Objectives:

  • Provide a login page where the user can enter their email address
  • On click of Sign-in user get the SSO popup (based Azure AD) to accept the terms and sign-in
  • Call graph API to retrieve user details (email ID, etc.)
  • Retrieve the sign in token and store in browser cache (localStorage) and use it for subsequent URL accesses (React routes).

I have come across MSAL (https://github.com/AzureAD/microsoft-authentication-library-for-js) which seems to be useful for this.

What I have tried:

ReactDOM.render(<MuiThemeProvider theme={theme}> <Router> <Switch> <Route path="/" exact component={Projects}/> <Route path="/projects" exact component={Projects}/> <Route path="/admin" exact component={Admin}/> <Route path="/projectstages/:projectNumber" exact component={ProjectStages}/> <Route path="/formspage" exact component={FormsPage}/> <Route path="/users" exact component={UserManagement}/> </Switch> </Router> </MuiThemeProvider>, document.getElementById('root'));

  • These routes (components) gets rendered within the main App.jsx component:

class App extends Component { render(){ return( <div className="App"> {this.props.children} </div> ); } }

How do I integrate this within my React app so that only authenticated users can access the React routes along with the objectives I mentioned above? Please let me know if I can provide more details or explain more about this.

2
Do you want call graph API so you need to generate accessToken Using Id Token for User Authentication?vishal pankhaniya

2 Answers

1
votes

This is usually achieved using higher-order-components.

The idea is, when you load a page that requires authentication, you call an api to get authentication using access token stored from your cookies or whatever storage you use. Then you need to wrap your protected routes to a HOC that checks the authentication data.

import React, {useState, useContext, useRef, createContext } from 'react'

const AuthContext = createContext(null)

export const withAuth = (requireAuth = true) => (WrappedComponent) => {
  function Auth(props) {
    const isMounted = useRef(false);
    // this is the authentication data i passed from parent component
    // im just using 
    const { loading, error, auth } = useContext(AuthContext);
    useEffect(() => {
      isMounted.current = true;
    }, []);
    if (!isMounted.current && loading && requireAuth !== 'optional') {
      return (<span>Loading...</span>);
    }
    if ((!auth || error) && requireAuth === true) {
      return (<Redirect to="/login" />);
    } if (auth && requireAuth === false) {
      return (<Redirect to="/" />);
    }
    return (
      <WrappedComponent {...props} />
    );
  }
  return Auth;
};

export function AuthenticationProvider(props) {
   const [auth, setAuth] = useState()
   const [error, setErr] = usetState()
   const [loading, setLoading] = useState(true)
   useEffect(() => {
     // get authentication here
     api.call('/auth')
       .then(data => {
         setAuth(data)
         setLoading(false) 
       })
      .catch(err => {
        setLoading(false)
        setErr(err)
      })

   })

  return (
    <AuthContext.Provider value={{ auth, error, loading }}>
       {children}
    </AuthContext.Provider>
  )
}

Then you can wrap your App with the Authentication Provider

  <AuthenticationProvider>
     <App/>
  </AuthenticationProvider>

And for each of the pages, you use the HOC like this

function ProtectedPage(props){
  // your code here
}

export default withAuth(true)(ProtectedPage)
0
votes

I'd like to recommend to use package for this: https://www.npmjs.com/package/react-microsoft-login

  1. Install:
yarn add react-microsoft-login
# or
npm i react-microsoft-login
  1. Import and configure component:
import React from "react";
import MicrosoftLogin from "react-microsoft-login";

export default props => {
  const authHandler = (err, data) => {
    console.log(err, data);
  };

  return (
    <MicrosoftLogin clientId={YOUR_CLIENT_ID} authCallback={authHandler} />
  );
};