Azure AD Login for your SPA using React Hooks

In this tutorial we are implementing Microsoft Azure Ad Login in React single-page app and retrieve user information using @azure/msal-browser.

The MSAL library for JavaScript enables client-side JavaScript applications to authenticate users using Azure AD work and school accounts (AAD), Microsoft personal accounts (MSA) and social identity providers like Facebook, Google, LinkedIn, Microsoft accounts, etc. through Azure AD B2C service. It also enables your app to get tokens to access Microsoft Cloud services such as Microsoft Graph.

Azure application registration

You can register you web app using  Microsoft tutorial.

In the below App.js file code we are using Context and Reducer for managing the login state. useReducer allows functional components in React access to reducer functions from your state management

First we initialize the initial values for reducer,
Reducers are functions that take the current state and an action as arguments, and return a new state result. In other words, (state, action) => newState

You can see the code form 17 line where we created reducer with using switch case “LOGIN” and “LOGOUT”. and from Line 58 we use the context that defined in line 6 and passing the reducer values to it.

And In a line 66 : we are checking the state.isAuthenticated or not , if it’s not the page redirect to the home page and if it’s Authenticated it will be redirected to the admin dashboard home page.

App.Js

import React, { useReducer } from "react";
import { createBrowserHistory } from "history";
import { Router, Route, Switch, Redirect } from "react-router-dom";
import AdminLayout from "layouts/Admin.js";
import HomeLayout from "layouts/Home.js";
export const AuthContext = React.createContext();
const hist = createBrowserHistory();


const initialState = {
    isAuthenticated: false,
    user: null,
    token: null,
    
};

export const reducer = (state, action) => {
    switch (action.type) {
        case "LOGIN":
            localStorage.setItem("user", action.payload.user);
            localStorage.setItem("token", action.payload.token);
            return {
                ...state,
                isAuthenticated: true,
                user: action.payload.user,
                token: action.payload.token
            };
        case "LOGOUT":
            localStorage.clear();
            return {
                ...state,
                isAuthenticated: false,
                user: null
            };
        default:
            return state;
    }
};

function App() {
    const [state, dispatch] = useReducer(reducer, initialState);

    React.useEffect(() => {
        const user = localStorage.getItem('user') || null;
        const token = localStorage.getItem('token') || null;

        if (user && token) {
            dispatch({
                type: 'LOGIN',
                payload: {
                    user,
                    token
                }
            })
        }
    }, [])
    return (
        <AuthContext.Provider
            value={{
                state,
                dispatch
            }}
        >
            <Router history={hist}>
                <Switch>
                    <div className="App">{!state.isAuthenticated ?
                        <>
                            <Route path="/home" render={(props) => <HomeLayout {...props} />} />
                            <Redirect to="/home" /> </> :
                        <><Route path="/admin" render={(props) => <AdminLayout {...props} />} />
                            <Redirect to="/admin/dashboard" /></>}</div>
                </Switch>
            </Router>
        </AuthContext.Provider>
    );
}

export default App;

Now we are coming the the Login Component with Azure Ad using with @azure/msal-browser

In a below code we are importing AuthContext from App.js and PublicClientApplication from @azure/msal-browser.

and In a 7th line we created constant variable “dispatch” with providing the reference of AuthContext then we created the msalInstandce variable using the PublicClientApplication and providing the clientId, authority and redirectUri in auth block.

In a line 22 we created the startlogin function then we created the loginRequest variable and providing the scope for login.

and In a line 31 we use the msalInstance.loginPopup(loginRequest) for getting pop up window for login and in a “loginRespone” variable save the login response. then we are fetching the username and token form loginRespone. dispatch to the AuthContext (see line 41).

And In a line 56 we created a button it’s call the startLogin function on click event.

Login.cs

import React from "react";

import { AuthContext } from "App";
import {  PublicClientApplication } from '@azure/msal-browser';

export const Login = () => {
  const { dispatch } = React.useContext(AuthContext);

  const msalInstance = new PublicClientApplication({

    auth: {
      clientId: "65395645-90dd-4436-84a4-47d7c0e961fc",
      authority: "https://login.microsoftonline.com/common",
      redirectUri: "https://localhost:3000",
    },
    cache: {
      cacheLocation: "sessionStorage",
      storeAuthStateInCookie: true,
           }
  });

  const startLogin = async (e) => {
    e.preventDefault();
   
    var loginRequest = {
      scopes: ["65395645-90dd-4436-84a4-47d7c0e961fc/.default"] // optional Array<string>
    };
   
    try {
      
      const loginResponse = msalInstance.loginPopup(loginRequest);
      
      const username = (await loginResponse).account.username;
      const token = (await loginResponse).accessToken;

      const resJson = {
        token: token,
        user: username
      };

      dispatch({
        type: "LOGIN",
        payload: resJson
      })
      console.log("Login successfully");
    } catch (err) {

      console.log("Authentication Failed.....");
      console.log(err);
    }
  }
 
  return (
    <div>

      <button className="btn btn-sm btn-outline-success my-2 my-sm-0" data-toggle="button" onClick={(e) => { startLogin(e) }}>Login</button>

    </div>

  );
};

export default Login;

Above you see we used the reducer and context in App.js file and crated a Login Component.

Conclusion

Now we can import the Login component anywhere in a project where we want to login button that uses the Azure AD for Authentication.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.