Integrate With Okta
This guide describes how to configure Okta to delegate to Beyond Identity for authentication during an OAuth2 authorization flow.
Prerequisites​
This guide uses NextAuth for all OAuth/OIDC flows. All code snippets are provided in the context of the NextAuth Example App.
Configuring NextAuth​
Under next-auth-example/pages/api/auth/[...nextauth].ts
, add the following Okta provider:
import OktaProvider from "next-auth/providers/okta";
...
providers: [
OktaProvider({
clientId: <OKTA_CLIENT_ID>,
clientSecret: <OKTA_CLIENT_SECRET>,
issuer: <OKTA_ISSUER>
})
]
...
Note that you'll need to fill in the <OKTA_CLIENT_ID>
, <OKTA_CLIENT_SECRET>
, and <OKTA_ISSUER>
with the values you generated when creating your application in Okta. See the following guide mentioned in the prerequisites.
Wiring up embedded.authenticate
​
Create a bi-authenticate.tsx
page under /next-auth-example/pages
. As long as your invoke_url
is configured properly, this is the page that will be redirected to during an authorization flow. copy the following code snippet into that page.
import { useEffect, useState } from "react";
import "bootstrap/dist/css/bootstrap.css";
import { Passkey } from "@beyondidentity/bi-sdk-js";
const BIAuthenticate = () => {
const [biAuthenticateResult, setBiAuthenticateResult] = useState("");
useEffect(() => {
// -- 1
const authenticate = async () => {
const BeyondIdentityEmbeddedSdk = await import("@beyondidentity/bi-sdk-js");
let embedded = await BeyondIdentityEmbeddedSdk.Embedded.initialize();
if (embedded.isAuthenticateUrl(window.location.href)) {
// Only authenticate if the URL is a "bi-authenticate" URL
let biAuthenticateUrl = window.location.href;
// -- 2
biAuthenticate(biAuthenticateUrl).then(redirectUrl => {
// -- 4
window.location.href = redirectUrl;
}).catch(error => {
setBiAuthenticateResult(error.toString());
});
}
}
authenticate().catch(console.error);
}, []);
// -- 3
async function biAuthenticate(url: string): Promise<string> {
const BeyondIdentityEmbeddedSdk = await import("@beyondidentity/bi-sdk-js");
let embedded = await BeyondIdentityEmbeddedSdk.Embedded.initialize();
// Display passkeys so user can select one
let passkeys = await embedded.getPasskeys();
let promptText = passkeys.map((passkey, index) => {
return `${index}: ${passkey.identity.username}`;
}).join("\n");
let selectedIndex = parseInt(prompt(promptText, "index")!!);
if (selectedIndex >= 0 && selectedIndex < passkeys.length) {
let selectedId = passkeys[selectedIndex].id;
// Perform authentication using selected id
let result = await embedded.authenticate(url, selectedId);
return Promise.resolve(result.redirectUrl);
} else {
// This will fail in core as it won't match to any id
return Promise.resolve("unknown_id");
}
}
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
}}
>
<div className="container">
<div className="row">
<div className="d-flex justify-content-center">
<div className="spinner-border" role="status">
<span className="sr-only"></span>
</div>
</div>
</div>
<div className="row">
{
biAuthenticateResult.length > 0 &&
<div className="row row-cols-1 row-cols-md-1 mt-3">
<div className="col">
<code>
{JSON.stringify(biAuthenticateResult, null, 2)}
</code>
</div>
</div>
}
</div>
</div>
</div>
);
};
export default BIAuthenticate;
What's happening here?​
- The
useEffect
is only called once on page load. In this function, we initialize the Beyond Identity SDK and useembedded.isAuthenticateUrl
to check if the current page that was redirected to is in fact a validbi-authenticate
URL. - If the URL is valid, we pull the URL using
window.location.href
and pass that directly intobiAuthenticate
in step 3. biAuthenticate
callsembedded.authenticate
with a validbi-authenticate
URL. This function performs a challenge/response against a passkey bound to your browser. Note that the callback inembedded.authenticate
contains logic in order to prompt a user to select a passkey if there is more than one.- Finally, the response of
embedded.authenticate
contains aredirectUrl
. Follow this redirect URL to complete the OAuth/OIDC flow.
What does it look like?​
Upon running the next auth example app and clicking on the sign in button, you'll see the provider you just added as shown in the image below. Clicking on that provider will go through an OAuth/OIDC that will result in fetching an id token that will log you in to the example app.