samples-js-react
samples-js-react copied to clipboard
Multiple Client Id and Multiple Issuer URL.
Hello team,
we have a requirement of having 2 CTA on home page. Employee Login and partner login.
.
For Employee Login we have different client Id and issuer url.
For Partner Login we have different client Id and issuer url.
Our application is single page application with react.
Below are the okta library we are using import { Security } from '@okta/okta-react'; import { OktaAuth, toRelativeUrl } from '@okta/okta-auth-js';
Please help me how handle this in react single page application.
You can try next approach.
Create 2 instances of OktaAuth
with different config - one for the Employee app and second one for the Partner app.
const oktaAuth1 = new OktaAuth(config1);
const oktaAuth2 = new OktaAuth(config2);
You need to store tokens in different places, please use different tokenManager.storageKey
for this:
const config1 = {
// clientId, issuer, redirectUri for app1
tokenManager: {
storageKey: 'app1',
},
};
const config2 = {
// clientId, issuer, redirectUri for app2
tokenManager: {
storageKey: 'app2',
},
};
Display 2 buttons for login that handles onClick accordingly:
oktaAuth1.signInWithRedirect()
-or-
oktaAuth2.signInWithRedirect()
Use different routes for employee and partner apps.
Wrap routes in separate <Security>
components with different oktaAuth
prop:
<Security
oktaAuth={oktaAuth1}
onAuthRequired={customAuthHandler1}
restoreOriginalUri={restoreOriginalUri}
>
<Switch>
<Route path="/app1" component={Home1} />
<Route path="/app1/login/callback" component={LoginCallback} />
<SecureRoute path="/app1/profile" component={Profile1} />
</Switch>
</Security>
<Security
oktaAuth={oktaAuth2}
onAuthRequired={customAuthHandler2}
restoreOriginalUri={restoreOriginalUri}
>
<Switch>
<Route path="/app2" component={Home2} />
<Route path="/app2/login/callback" component={LoginCallback} />
<SecureRoute path="/app2/profile" component={Profile2} />
</Switch>
</Security>
You can also ask in https://devforum.okta.com/ as it's not typical usage of okta-auth-js and okta-react
Thanks for responding.
We have single app only with single code base And on home page we need to display 2 cta. We do not have two different app. Same app with 2 different okta client I'd and issuer url.
I have one login.jsx file having both the cta and one app.jsx file. Please suggest me how it can be handled. Thanks
Then you can have 1 <Security>
component.
You still need to create 2 OktaAuth instances with different configs:
(You can leave default options for tokenManager
and not customize storageKey
as I mentioned earlier)
const oktaAuth1 = new OktaAuth(config1); // config for employee
const oktaAuth2 = new OktaAuth(config2); // config for partner
Use them in login button handlers accordingly:
<button onClick={() => oktaAuth1.signInWithRedirect()}>Employee login</button>
<button onClick={() => oktaAuth2.signInWithRedirect()}>Partner login</button>
Please set up 2 different Sign-in redirect URIs
in your Okta app configurations.
Eg. https://<your domain>/employee/login/callback
and https://<your domain>/partner/login/callback
.
You can determine dynamically what OktaAuth instance of two should be passed to <Security>
as follows:
const clientIdFromToken = oktaAuth1.tokenManager.getTokensSync()?.accessToken?.claims?.cid;
const oktaAuth = clientIdFromToken === oktaAuth1.options.clientId || window.location.href.includes(oktaAuth1.options.redirectUri) ? oktaAuth1 : oktaAuth2;
Then you can wrap your routes and components in single <Security>
component:
<Security
oktaAuth={oktaAuth}
onAuthRequired={customAuthHandler}
restoreOriginalUri={restoreOriginalUri}
>
<Switch>
<Route path="/" component={Home} />
<Route path="/employee/login/callback" component={LoginCallback} />
<Route path="/partner/login/callback" component={LoginCallback} />
<SecureRoute path="/profile" component={Profile} />
</Switch>
</Security>
(Note 2 different routes handled by same LoginCallback
component)
@denysoblohin-okta could you explain how this should be setup in the event a single SPA needed to communicate with 2 different authorization servers? The above works fine if you need one or the other, but what if you needed to maintain multiple tokens?
We have API A which is secured by AuthServer 1 and API B which is secured by AuthServer 2. The SPA needs to be able to talk with both APIs and therefore needs two separate tokens.
Am I approaching this totally wrong? It feels like I'm fighting the tool.
okta-react
is designed to be provider of one instance of OktaAuth.
If you really need 2 instances of OktaAuth together, please see my first comment about creating two instances of OktaAuth using different tokenManager.storageKey
. You can use them in your app without need of okta-react
.
Can you explain the need of 2 issuers in your app?
@denysoblohin-okta We have been following the best practices for Authorization Servers here https://developer.okta.com/docs/concepts/api-access-management/#authorization-server
This suggests having one Authorization Server per API product. Our use case now dictates that our SPA now needs to communicate with two separate API's, each behind their own unique Authorization Server. I'm under the impression the SPA will need to obtain and store an access token for each authorization server.
I have been able to use okta-auth-js
to obtain the tokens, but unfortunately cannot find a way to continue using okta-react
, specifically the LoginCallback
component, multiple times. The tokens seem to collide with eachother even after setting tokenManager.storageKey
. Is there a way to continue to get the benefits that okta-react
provides or does this use case require doing everything by hand with the lower level okta-auth-js
package?
okta-react
is a wrapper for okta-auth-js
and provides a few conveniences for the React ecosystem, like <LoginCallback />
and SecureRoute
. It's completely reasonable to use okta-auth-js
directly, instead of okta-react
if you find that easier. That being said, I think a component structure like this may solve your problem:
<Switch>
<Route path="/employee">
<Security oktaAuth={oktaAuth1}>
<Switch>
<Route path="/" component={Employee} />
<Route path="/employee/login/callback" component={LoginCallback} />
</Switch>
</Security>
</Route>
<Route path="/partner">
<Security oktaAuth={oktaAuth2}>
<Switch>
<Route path="/" component={Partner} />
<Route path="/partner/login/callback" component={LoginCallback} />
</Switch>
</Security>
</Route>
</Switch>
Utilizing nested routes allows for the oktaAuth
instance to be unique for each LoginCallback
(it's provided via React context API via the Security
component)
However, it may be easier to write your own LoginCallback
component that determines which oktaAuth
instance to use based on the auth data provided during redirect