javascriptreactjsazureazure-active-directorymicrosoft-graph-api

How to get last login date & time for the logged in user in azure ad?


I'm using Azure AD for authentication in a React.js application. I need to retrieve the last login time of the currently logged-in user and store it in the database for use on the user management page.

Users are already being saved in the database, and I want to track the last login timestamp for each user. However, since authentication is handled by Azure AD, I don't have direct control over the login process to record this timestamp myself. Therefore, I need to fetch the user's last login time from Azure AD.


Solution

  • To retrieve the last login date & time for the logged in user you can make use of Microsoft Graph API query.

    According to this MsDoc, the signed-in user must have a supported Microsoft Entra role such as Security Reader or Reports Reader and the application must be granted with AuditLog.Read.All

    Granted AuditLog.Read.All delegated API permission:

    pic1

    Configured redirect URL under SPA:

    pic2

    Assigned Global Reader role (active assignment) to the user:

    pic3

    Now used the below code to fetch the last login date & time for the logged in user:

    authConfig.js

    export const msalConfig = {
      auth: {
        clientId: "ClientID",
        authority: "https://login.microsoftonline.com/TenantID",
        redirectUri: "http://localhost:3000",
      },
      cache: {
        cacheLocation: "localStorage",
      },
    };
    
    export const loginRequest = {
      scopes: ["User.Read", "AuditLog.Read.All"],
      prompt: "select_account",
    };
    

    index.js

    // src/index.js
    
    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App";
    import { PublicClientApplication } from "@azure/msal-browser";
    import { MsalProvider } from "@azure/msal-react";
    import { msalConfig } from "./authConfig";
    
    const msalInstance = new PublicClientApplication(msalConfig);
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      <MsalProvider instance={msalInstance}>
        <App />
      </MsalProvider>
    );
    

    App.js

    // src/App.js
    
    import React from "react";
    import { useMsal, useIsAuthenticated } from "@azure/msal-react";
    import { loginRequest } from "./authConfig";
    import axios from "axios";
    
    function App() {
      const { instance, accounts } = useMsal();
      const isAuthenticated = useIsAuthenticated();
    
      const handleLogin = async () => {
        try {
          await instance.loginPopup(loginRequest);
        } catch (error) {
          console.error("Login failed", error);
        }
      };
    
      const handleLogout = async () => {
        try {
          const account = accounts[0];
          await instance.logoutPopup({ account });
        } catch (error) {
          console.error("Logout failed", error);
        }
      };
    
      const getSignInActivity = async () => {
        const account = accounts[0];
        if (!account) return;
    
        try {
          const response = await instance.acquireTokenSilent({
            ...loginRequest,
            account,
          });
    
          const graphResponse = await axios.get(
            "https://graph.microsoft.com/v1.0/me?$select=id,signInActivity",
            {
              headers: {
                Authorization: `Bearer ${response.accessToken}`,
              },
            }
          );
    
          const activity = graphResponse.data.signInActivity;
          alert(
            "Last Sign-In: " + (activity?.lastSignInDateTime || "Not found")
          );
        } catch (error) {
          console.error("Graph API Error", error);
        }
      };
    
      return (
        <div style={{ padding: 30 }}>
          <h2>Azure AD Login App</h2>
    
          {!isAuthenticated ? (
            <button onClick={handleLogin}>Login</button>
          ) : (
            <>
              <p>Welcome, <strong>{accounts[0]?.username}</strong></p>
              <button onClick={getSignInActivity}>Get Last Sign-In</button>
              <button onClick={handleLogout} style={{ marginLeft: 10 }}>
                Sign out / Switch Account
              </button>
            </>
          )}
        </div>
      );
    }
    
    export default App;
    

    enter image description here

    User login:

    pic

    When clicked on Get last sign-in got the response successfully:

    pic