Session Token and Session Cookie

Hello,

I configured SAML Applications on Okta and use apis and redirections to redirect a user to the SAML Application.
My code does the following:

  • uses a primary authentication API (post to /api/v1/authn) to get aSsession Token,
  • then redirects to the embed link of the target application with a Session Token URL parameter.

The first user is redirected and correctly authenticated to the SP. Okta sets a cookie in the browser.
If I test with a second user, I get a second SessionToken, and pass it in URL Parameter.

However, when I redirect to Okta, it seems the SessionToken is not taken into account, and the first user is sent to the SP Application. It seems the first SessionToken has set a cookie, and the second SessionToken is not changing the cookie.

How can I solve this problem?

Thanks!

When you try to pass a session token in a URL parameter to authenticate a user who is already logged in, Okta may ignore the token and rely on the existing session cookie instead (for Okta Classic orgs). This is because the session cookie takes precedence over any session token that may be present in the URL.

Can you logout the first user prior to testing with the second user? You can use the /api/v1/sessions/me endpoint to close an existing session for the current user. This endpoint takes no parameters, and will return a 204 No Content response on success.

For example:

curl -v -X DELETE "https://your-org.okta.com/api/v1/sessions/me"

If you run into issues using this endpoint in a browser, be sure to check out the following guide about 3rd party cookies.

1 Like

To follow up on @adam_okta’s post, here’s a sample fetch request so you can make this call in your browser:

fetch('https:/oktaDomain/api/v1/sessions/me', {method: 'DELETE', credentials: "include"})
  .then((response) => {
    return response.json();
  })

1 Like

Hello,
thanks for your fast answer. I already tried what you mentioned, without success:

I copy my code below: the function getSessionToken first tries to delete the current session, then retrieves a session token. But I get a 404 when I try to close the previous session, even if it exists in effec.
I do receive a different sessionToken, and even if closing the previous session ends in 404, passing the new session token keeps the first user logged in.

export async function closeCurrentSession() {
   try {
      const requestUrl = `https://${env.OKTA_DOMAIN}/api/v1/sessions/me`;
      const response = await axios.delete(requestUrl, oktaConfig);
   } catch (error) {
      error.source = cOkta;
      throw error;
   }

}

export async function tryCloseCurrentSession() {
   try {
      await closeCurrentSession();
   } catch (error) {
      logger.debug('Cannot close current session');
      logger.error(error);
   }
}

export async function simpleAuthentication(login: string, password: string): Promise<string> {
   try {
      const authUrl = `https://${env.OKTA_DOMAIN}/api/v1/authn`;

      const authResponse = await axios.post(authUrl, {
         username: login,
         password: password,
         options: {
            multiOptionalFactorEnroll: true,
            warnBeforePasswordExpired: true
         }
      }, oktaConfig);

      return authResponse.data.sessionToken;
   } catch (error) {
      error.source = cOkta;
      logger.error(error);
      throw error;
   }
}

export async function getSessionToken(user: tUser): Promise<string> {
   await tryCloseCurrentSession();
   return await simpleAuthentication(user.login, getPassword(user));
}

It seems that the problem is, the cookie for the session is set by okta in the redirection, when the code redirects to https://{application_embed_link}?sessionToken={sessionToken}.

And so when I query the current session from my code, the code does not have the session cookie, so I get 404.

I tried to create a session from a session token.
But then the redirection with the session token does not work: the user is not logged on Okta.

Do you have the withCredentials option to true in the axios request configuration?

If it’s already present in the oktaConfig object you don’t need to do this. However, if not…

export async function closeCurrentSession() {
   try {
      const requestUrl = `https://${env.OKTA_DOMAIN}/api/v1/sessions/me`;
      const response = await axios.delete(requestUrl, {
         ...oktaConfig,
         withCredentials: true // Include cookies in the request and response headers
      });
   } catch (error) {
      error.source = cOkta;
      throw error;
   }
}

Thanks, it was not the case. I repeated the test after adding this to the “oktaConfig” json structure, but I get the same result.

The code is the following:

   await okta.tryCloseCurrentSession()
   sessionToken = await okta.getSessionToken(req.session.user)
   const finalUrl = (redirectUrl.trim() + `?sessionToken=${sessionToken}`)
   logger.debug('Outbound router redirects to ' + finalUrl)
   res.redirect(finalUrl)
}

where tryCloseCurrentSession was defined earlier. It still ends in 404.

I use nodejs express, I don’t know if res.redirect has an interaction with the axios framework.
For now the only very ugly workaround I have put in place “successfully” is to set the lifetime of the session in Okta to 1 minute… But I take the very ugly assumption that 2 different users will not use the same browser in less than 1 minute… I am still looking for a better solution though.

Thanks!

So you are sending the sessionToken to an endpoint that is able to convert it into a session cookie, right (I saw you mentioned the app embed link earlier)?

If you try to navigate to the Org in your browser after this redirect, does the user get prompted to login again or are they just redirected to their dashboard/default app?

1 Like

Yes, I use the embed link of an application registered as a SAML App in Okta, with the session Token in parameter: the user is implicitly logged in (no login prompt), and is redirected to the SAML App.

Okta creates the session cookie from the link if and only if a session cookie does not already exist. And this is where my problem is. The second user using the same browser is authenticated to the SAML app as the first user.

It seems like, since the session cookie is not created during a post / get from my axios framework, it is not retained in its state for later use.

I tried to use the API Create Session from Session Token, but then when I redirect to the Embed Link, with or without the session token, the user is prompted to enter his login / password, which is what I want to avoid.

Correct, there must not be a Session Cookie in the browser/for the Okta domain used for the sessionToken to be accepted/exchanged for a session cookie. If you need to support this use case, the first user must be logged out first.

Are you saying you’re not seeing the session cookie set even if there wasn’t one already present in the browser?

If so, you don’t happen to be using both the *.okta.com domain to log users into a specific app as well as a custom domain configured on your org, do you? Because the session is set at the domain level (via the session cookie), so maybe that’s related to what you’re seeing, where the user is switching domains and therefore has to autheticate again

2 Likes

Hello Andrea, I repeat my usecase:

0 - To begin with, I clear all Okta cookies in the browser.

A - Access for the First user
1 - Using API, I get a session cookie for a user
2 - I redirect this user to the SAML Application embed link, with the ‘sessionToken’ URL parameter.
3 - The user is seamlessly redirected to the SAML Application, and logged in this application => it works.

B - An other user uses the same browser, to access the SAML Application.
1 - Using API, I get a session cookie for the second user.
2 - I redirect this user to the SAML Application embed link, with the ‘sessionToken’ URL parameter.
3 - The user is seamlessly redirected to the SAML Application, and logged in AS THE FIRST USER to this application => it DOES NOT work.

Plus:

  • If before step 1 or in-between step 1 and 2, I tried to logout the current session, using API, no session is found: the cookie is set in the browser by the redirection, but is not accessible by the axios framework with “withCredentials=true”, because the session is not created by the axios framework.
    => I do not know when, and how I coul log out the user.

Is it more clear?

So the questions are:

  • how to log out a user redirected to an embed link with a session token?
  • how to log in a second user using an embed link, on the same browser?

I would have expected the sessionToken provided in the URL the second time to take precedence over the sesson cookie in the browser, so the cookie is refreshed with the second user session.

Regards,
Joel

Hello Andrea, I hope you haven’t given up on me :slight_smile:

I think you have the wrong expectation. After the first user logs in, they have an active session with Okta. You can’t just make another request with a new session token and expect that the previous user will be logged out. You should close the Okta session for the first user before trying to login with a different user.

In theory, the DELETE call to /api/v1/sessions/me should close the Okta session. If you are using a custom url domain, then you will need to modify the request url to htttps://${custom_url_domain}/api/v1/sessions/me instead of https://${okta_domain}/api/v1/sessions/me.

1 Like

Hello Warren,
thanks for the support.

I tried to log out, using a call to Delete as you mentioned, without success: I get a http error 404.
The value of my env variable for the okta doamin is good: when I forward to the embed link, and when I call the delete api, I use the same okta domain, which is a custom one tailored to the tenant I use.

It seems that when I use response.redirect to redirect the user to the embedlink, the cookie set by the browser is not accessible by the axios framework, since it’s not a direct request done by the framework which set the cookie. That’s my assumption.

I tried using the OKTA api creating a session with a session token, so the cookie is set by the framework, but I got no luck there.