Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep Me Signed In Not Working, x-ms-cpim-sso:{Id} Cookie Not Persisting #7288

Open
1 of 2 tasks
akopplinufpi opened this issue Sep 3, 2024 · 5 comments
Open
1 of 2 tasks
Labels
b2c Related to Azure B2C library-specific issues bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-browser Related to msal-browser package msal-react Related to @azure/msal-react Needs: Attention 👋 Awaiting response from the MSAL.js team public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.

Comments

@akopplinufpi
Copy link

akopplinufpi commented Sep 3, 2024

Core Library

MSAL.js (@azure/msal-browser)

Core Library Version

^3.4.0

Wrapper Library

MSAL React (@azure/msal-react)

Wrapper Library Version

^2.0.7

Public or Confidential Client?

Public

Description

We are experiencing an issue where the user selects "Keep Me Signed In" (KMSI) when logging in. But the user is unable to get new tokens after 24 hours without interaction (acquiretokensilent VS acquiretokenredirect).

In the Microsoft documentation it is stated that the cookie used to persist the KMSI setting is called x-ms-cpim-sso:{Id}

image

source: https://learn.microsoft.com/en-us/azure/active-directory-b2c/cookie-definitions

I verified that the token is being successfully stored in the browser:

image

The expiration date on the cookie is 90 days from today. However, when I close the browser and re-open, the cookie is no longer there. The fact that the cookie is getting deleted therefore is breaking the KMSI functionality. I have tested this in both Chrome and Edge.

Here are the SPA redirect URI's that we are using the in the app

image

We are using user flow

image

We have keep me signed in selected

image

Error Message

No response

MSAL Logs

main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:initializeStart
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:initializeEnd
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:handleRedirectStart
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - MsalProvider - msal:handleRedirectStart results in setting inProgress from startup to handleRedirect
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
jobs:1 GET https://(my-domain.com)/favicons/site.webmanifest 404 (Not Found)
site.webmanifest:1 Manifest: Line: 1, column: 1, Syntax error.
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - BrowserCacheManager: addTokenKey - idToken added to map
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - BrowserCacheManager: addTokenKey - refreshToken added to map
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:loginSuccess
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:handleRedirectEnd
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - MsalProvider - msal:handleRedirectEnd results in setting inProgress from handleRedirect to none
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
main.be3b1d23.js:2 GET https://(my-domain.com)/api/jobs/jobdetails 401 (Unauthorized)
(anonymous) @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
xhr @ main.be3b1d23.js:2
HI @ main.be3b1d23.js:2
Promise.then (async)
request @ main.be3b1d23.js:2
QT.forEach.YI. @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
makeGetRequest @ main.be3b1d23.js:2
getAPIResponseAsync @ main.be3b1d23.js:2
loadJobData @ main.be3b1d23.js:2
loadJobDataAsync @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
ol @ main.be3b1d23.js:2
_c @ main.be3b1d23.js:2
cc @ main.be3b1d23.js:2
Wo @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
Cc @ main.be3b1d23.js:2
ic @ main.be3b1d23.js:2
C @ main.be3b1d23.js:2
I @ main.be3b1d23.js:2
main.be3b1d23.js:2 Unauthorized, trying to get token and retrying request. Route: jobs/jobDetails
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:acquireTokenStart
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getAccessToken - No token found
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getRefreshToken - returning refresh token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [3e0333b9-cdf7-4819-992f-b09dafa3560f] : @azure/msal-common@14.4.0 : Info - Token refresh is required due to cache outcome: 2
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:acquireTokenFromNetworkStart
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getRefreshToken - returning refresh token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 GET https://(my-domain.com)/api/user/userrole 401 (Unauthorized)
(anonymous) @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
xhr @ main.be3b1d23.js:2
HI @ main.be3b1d23.js:2
Promise.then (async)
request @ main.be3b1d23.js:2
QT.forEach.YI. @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
makeGetRequest @ main.be3b1d23.js:2
getAPIResponseAsync @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
ol @ main.be3b1d23.js:2
_c @ main.be3b1d23.js:2
cc @ main.be3b1d23.js:2
Wo @ main.be3b1d23.js:2
(anonymous) @ main.be3b1d23.js:2
Cc @ main.be3b1d23.js:2
ic @ main.be3b1d23.js:2
C @ main.be3b1d23.js:2
I @ main.be3b1d23.js:2
main.be3b1d23.js:2 Unauthorized, trying to get token and retrying request. Route: User/UserRole
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - BrowserCacheManager: addTokenKey - accessToken added to map
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-browser@3.5.0 : Info - Emitting event: msal:acquireTokenSuccess
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:52 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:55 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:55 GMT] : [] : @azure/msal-common@14.4.0 : Info - CacheManager:getIdToken - Returning id token
main.be3b1d23.js:2 [Tue, 03 Sep 2024 14:20:55 GMT] : [] : @azure/msal-react@2.0.7 : Info - useAccount - Updating account

Network Trace (Preferrably Fiddler)

  • Sent
  • Pending

MSAL Configuration

import { LogLevel } from "@azure/msal-browser";
// Browser check variables
// If you support IE, our recommendation is that you sign-in using Redirect APIs
// If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check
const ua = window.navigator.userAgent;
const msie = ua.indexOf("MSIE ");
const msie11 = ua.indexOf("Trident/");
const msedge = ua.indexOf("Edge/");
const firefox = ua.indexOf("Firefox");
const isIE = msie > 0 || msie11 > 0;
const isEdge = msedge > 0;
const isFirefox = firefox > 0; // Only needed if you need to support the redirect flow in Firefox incognito

/**
 * Enter here the user flows and custom policies for your B2C application
 * To learn more about user flows, visit: https://docs.microsoft.com/en-us/azure/active-directory-b2c/user-flow-overview
 * To learn more about custom policies, visit: https://docs.microsoft.com/en-us/azure/active-directory-b2c/custom-policy-overview
 */
export const b2cPolicies = {
	names: {
		signUpSignIn: "B2C_1_{my-b2c-tenant}.SignInSignUp",
		editProfile: "B2C_1_{my-b2c-tenant}.EditProfile"
	},
	authorities: {
		signUpSignIn: {
			authority:
				"https://{my-b2c-tenant}.b2clogin.com/{my-b2c-tenant}.onmicrosoft.com/B2C_1_{my-b2c-tenant}.SignInSignUp"
		},
		editProfile: {
			authority:
				"https://{my-b2c-tenant}.b2clogin.com/{my-b2c-tenant}.onmicrosoft.com/B2C_1_{my-b2c-tenant}.ProfileEditing"
		}
	},
	authorityDomain: "{my-b2c-tenant}.b2clogin.com"
};

// Config object to be passed to Msal on creation
export const msalConfig = {
	auth: {
		clientId: "13c05f42-a185-47f3-a9b4-15cab19dc7b3",
		authority: b2cPolicies.authorities.signUpSignIn.authority,
		knownAuthorities: [b2cPolicies.authorityDomain],
		// redirectUri: window.location.origin + "/jobs",
		postLogoutRedirectUri: "/",
		scopes: [
			"https://{my-b2c-tenant}.onmicrosoft.com/api/TrussTrax.Read",
			"https://{my-b2c-tenant}.onmicrosoft.com/api/TrussTrax.Write"
		]
	},
	cache: {
		cacheLocation: "localStorage",
		storeAuthStateInCookie: isIE || isEdge || isFirefox
	},
	system: {
		loggerOptions: {
			logLevel: LogLevel.Info,
			loggerCallback: (level, message, containsPii) => {
				if (containsPii) {
					return;
				}
				switch (level) {
					case LogLevel.Error:
						console.error(message);
						return;
					case LogLevel.Info:
						console.info(message);
						return;
					case LogLevel.Verbose:
						console.debug(message);
						return;
					case LogLevel.Warning:
						console.warn(message);
						return;
					default:
						return;
				}
			}
		}
	}
};

Relevant Code Snippets

in app.jsx, we wrap our /jobs route in a component we call .

<Route
    path="/jobs"
    element={
        <RequireAuth>
	    <PageTracking route="/jobs">
	        <Jobs
		    isLoading={isLoading}
		    jobsStatuses={jobStatuses}
		/>
            </PageTracking>
	</RequireAuth>
    }
/>

here is the relevant code from RequireAuth

return (
	<>
		<MsalAuthenticationTemplate
			interactionType={InteractionType.Redirect}
			authenticationRequest={config.auth.scopes}
			errorComponent={ErrorComponent}
			loadingComponent={LoadingComponent}>
			{role === null ? <CenterSpinner /> : role === "None" ? <Welcome /> : children}
		</MsalAuthenticationTemplate>
	</>
);

Here is the code from our API class that is responsible for getting a valid token and attaching it to network requests. After 24 hours, when a network request is made, the user is redirected to /notauthorized

public getTokenAsync = async (redirectOnUnauthorized: boolean = true) => {
		const activeAccount = this.msalInstance.getActiveAccount();
		const accounts = this.msalInstance.getAllAccounts();

		const request = {
			scopes: this.msalInstance.controller.config.auth.scopes,
			account: activeAccount || accounts[0]
		};

		try {
			// tokens expire every 20 or 30 mins. politely ask MSAL for a new token
			const authResult = await this.msalInstance.acquireTokenSilent(request);
			return authResult.accessToken;
		} catch (error) {
			// if we cant get a token, the user needs to re-authenticate

			if (redirectOnUnauthorized) {
				if (window.location.pathname !== "/notauthorized") {
					window.location.href = "/notauthorized";
				}
			} else {
				throw new Error("User not authorized");
			}

			// TODO this would be nice to get this working
			// const result = await this.msalInstance.acquireTokenRedirect(request);
			// return result.accessToken;
		}
	};

If the users role is null, we we render a spinner, while the user is being redirected to B2C to sign in. You can see the scopes that are used to sign in from the MSAL Configuration above. Once the user comes back from being redirected to B2C, the user gets a token, which is then used to make an API call to get the role. Once the user has their role, they are let in to the app, which is rendered by {children}

Reproduction Steps

If you would like to reproduce this issue in our dev environment, please contact me and I will be able to get you access.

Expected Behavior

The expected behavior is that the cookie x-ms-cpim-sso:{Id} should not get deleted when the browser closes. it should stay in the cookies in the browser and allow the user to stay signed in for up to 90 days. What we are experiencing is that the user is again unable to retrieve a token after 24 hours without interaction.

Identity Provider

Azure B2C Custom Policy

Browsers Affected (Select all that apply)

Chrome, Edge

Regression

No response

Source

External (Customer)

@akopplinufpi akopplinufpi added bug-unconfirmed A reported bug that needs to be investigated and confirmed question Customer is asking for a clarification, use case or information. labels Sep 3, 2024
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs: Attention 👋 Awaiting response from the MSAL.js team label Sep 3, 2024
@github-actions github-actions bot added b2c Related to Azure B2C library-specific issues msal-browser Related to msal-browser package msal-react Related to @azure/msal-react public-client Issues regarding PublicClientApplications labels Sep 3, 2024
@akopplinufpi
Copy link
Author

akopplinufpi commented Sep 3, 2024

Update: Ive found that if I shift+F5 refresh, then the cookie re-appears in the browser. However this still does not explain why users are booted out after 24 hours

@sameerag
Copy link
Member

sameerag commented Sep 6, 2024

@akopplinufpi A SPA RT is only valid for 24 hrs by design in the default case. MSAL JS however does not control the browser cookies or the KMSI cookie presence enabling the server to issue a valid RT silently. Did you check with B2C service if they have an explanation? Support link here.

Please let me know if there is no response and I can try engage the B2C team here.

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Author Feedback Awaiting response from issue author and removed Needs: Attention 👋 Awaiting response from the MSAL.js team labels Sep 6, 2024
@akopplinufpi
Copy link
Author

Hi @sameerag thank you for taking the time to respond! I went to create the support request, and it looks like the "Technical" issue type is not available. I went ahead and created a request anyways... Can you ping the B2C team to see if they got the request? support request number: 2409090040008015

image

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 Awaiting response from the MSAL.js team and removed Needs: Author Feedback Awaiting response from issue author labels Sep 9, 2024
@jsomdev
Copy link

jsomdev commented Sep 16, 2024

@akopplinufpi we are having the same issue

@akopplinufpi
Copy link
Author

@jsomdev unfortunately the response that I have gotten from Microsoft from the ticket that I created has been 1) it should be working as expected; and 2) its probably something you are doing wrong within your own application. However, we are not doing anything to interact with cookies directly - we are using @azure/msal-react and @azure/msal-browser libraries for authentication, so I dont see how it could be something that we are doing within the application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
b2c Related to Azure B2C library-specific issues bug-unconfirmed A reported bug that needs to be investigated and confirmed msal-browser Related to msal-browser package msal-react Related to @azure/msal-react Needs: Attention 👋 Awaiting response from the MSAL.js team public-client Issues regarding PublicClientApplications question Customer is asking for a clarification, use case or information.
Projects
None yet
Development

No branches or pull requests

3 participants