Multiple apps in the same portal

Hi,

We have Okta set up for authentication on a number of SPA’s which make up our portal using OpenID Connect. Each app is standalone and hosted on different servers but all are accessed from a central hub. We provide internal and external users access to the hub, both of which are currently added to the Okta user directory.

Each app uses the login widget, all using the same Okta authentication server. I want SSO across this suite of apps but I’m not sure on how best to implement it. Can someone point me in the right direction please?

cheers
Martin

2 Likes

Can no one help with this?

I assume all your SPA apps use the same logic that takes a user to Okta’s login widget. When a user has logged in to Okta from one app, Okta will store a session cookie for that user in the browser. When the user navigates to another one of your apps, since it’s the same browser, the Okta cookie will be sent to Okta by the browser, and OKta login widget will not need to show, since the cookie proved the user has logged in recently. Your second app should/would silently let the user pass authentication since Okta let it pass.

The part about Okta cookie is similar to the other question by the following link, although I understood yours are SPA apps, and the apps in the other question likely use authentication middleware on the server side. But still, the Okta cookie usages are the same.

Using the Okta custom login we only get a okta-oauth-state and okta-oauth-nonce cookies stored. We dont get a session token to exchange for a session cookie

login.component.ts

this.oktaSignIn = new OktaSignIn({
baseUrl: ‘https://dev-66666.oktapreview.com’,
clientId: ‘{client id}’
redirectUri: ‘http://localhost:4200/implicit/callback’,
authParams: {
issuer: ‘default’,
responseType: [‘id_token’,‘token’],
display: ‘page’
}
});

ngOnInit()…

if (this.oktaSignIn.tokenManager.get(‘id_token’)) {
this.router.navigate([‘home’]);
// Redirected has token in URL
} else if (this.oktaSignIn.token.hasTokensInUrl()) {
// The user has just successfully completed a redirect
this.oktaSignIn.token.parseTokensFromUrl((response) => {
this.oktaSignIn.tokenManager.add(‘id_token’, response[0]);
this.oktaSignIn.tokenManager.add(‘access_token’, response[1]);
this.user = response[0].claims.email;
this.router.navigate([‘home’]);
}
);
} else {
this.oktaSignIn.renderEl({el: ‘#okta-login-container’}, (response) => {
console.log(response);
});
}

My understanding of the implicit flow is that you authenticate using either the custom login or Okta hosted login widget using username/password.

The result of which is id/access tokens stored in the browsers local storage and state/nonce cookies being stored as well. No sessionToken is returned in implicit flow which means no session cookie can be requested and stored in the browser.

If this is the case how can SSO be implemented for another app on a different server? Should we be using the API directly?

If we use the API then I would assume the following process…

/authn for authentication which returns a sessionToken
/session to create a session cookie from the sessionToken which can be stored

Once the session cookie is in place then I presume navigating to App B from App A would cause App B to silently authenticate?

I understood implicit flow returns both id/access tokens to the client (browser in SPA case), without the involvement of an auth code.

Using the browser’s debug tool or Fiddler, you can observe the cookies set by Okta after the correct Okta credential are entered. The cookie names may look like “sid”, “JSESSIONID”. To test cookie’s effect, you can log in using one of your SPA apps first, then open another browser tab/window, go to https://myorg.oktapreview.com. If you are not asked for Okta credential, then Okta cookies are present and used.

Hi,

Currently I have the same SPA deployed twice on my local machine to different ports. Using the login widget with okta-auth-js no session cookie is set so no SSO is available and I have login to each individually.

If I was to change the app to use /authn for authentication in App A, and then /sessions, to create a session cookie from the sessionToken, I should be able to login to App B without entering my details I would assume? This would cover when using SSO across apps in the same domain but how would this work cross domain?

Cookies are not available cross domain so if I login to App A on domain1.com and retrieve/store my session cookie it will not be available on App B on domain2.com. If both apps are on the same domain then this process works but not if the SPA’s are hosted on different domain names?

Thanks for your help on this, appreciate your time.

cheers
Martin

Just giving this a little bump…

Hmm, did not see any notification about new replies to this thread.

You are right that cookies are domain & port specific. Okta session cookie will allow the browser to log into your second app without seeing Okta login widget.

A few thoughts on why it did not work - first, Okta session cookie is session bound, it’s gone when

  • The browser processes are killed, which cleans up all session cookies, or
  • User clicked Okta logout link, or
  • Session expired (2 hours of inactivity)

Second, it’s a puzzle that you do not see Okta session cookie. I have seen the session behavior between an Okta SAML app and Okta dashboard. Could there be anything in your app configuration that prevent session behavior/cookie?

And last, looks like this thread is related to your question:

Hope that helps.

Hi,

I’ve resolved this, I was redirecting to my own component method and storing the tokens manually. I changed it to return to implicit/callback which stored the session cookie and allows my SSO to work perfectly

Thank you for your time on this!

cheers
Martin

Awesome. Glad for you.

Sorry to say I have hit another snag that I could use some guidance with if possible!

I have both apps now running, when I login to App A a session cookie is stored along with an id & access token. When I then navigate to App B the session cookie is present and, using okta-signin-widget, I can see that I have an okta session when calling session.get().

However the id and access tokens are not present so I am then using okta-auth-js to make a call to token.getWithoutPrompt to retrieve my tokens and add them to the token manager.

This all works perfectly and both apps are in the state that I would like to see them in for SSO.

When I hit logout on either of the apps I clear the tokenManager and logout of my okta session. This works perfectly for the app I am currently in.

The issue I have hit comes when I then navigate to the other app. If there is no okta session then the app clears the tokenManager and forces the user to login again. However I then get an error in the console…

error.errorCode: login_required, error.description: The client specified not to prompt, but the user is not logged in.

ERROR Error: Uncaught (in promise): OAuthError: The client specified not to prompt, but the user is not logged in.

I’ve added some console.logging to my code to ensure that it doesnt hit the getWithoutPrompt call that I have. I’m guessing this comes from within the login widget somewhere?

Steps:

  1. Login to AppA with implicit flow redirecting to /implicit/callback
  2. Tokens in local storage along with cookie for state and nonce
  3. Navigate to AppB
  4. AppB identifies that there is an Okta session and uses okta-auth-js to call getWithoutPrompt to retrieve id and access tokens to store using TokenManager
  5. Logout of AppB - clears tokenManager and closes OktaSession
  6. Navigate back to AppA which clears the tokenManager and redirects to login page

It is at Step 6 that I receive the OAuthError. The apps both behave as expected but I don’t want any errors displayed in the browser

Cheers
Martin

okta-sign-in.min.js:14 is the line I get the error from

Hi @scoobymib3
I have similar use case of two apps within different domain where App B would be started through one of the button click in App A.
I was wondering if you could please provide me an example code on how you are using getWithoutPrompt in Step 4.

I am able to get the OktaSession using signWidget but not sure how to use that to call getWithoutPrompt method since session doesnt have sessionToken in it.

thank you,
Chirag