Integrate With Okta
This guide describes how to configure Okta to delegate to Beyond Identity for authentication during an OAuth2 authorization flow.
Prerequisites​
Before calling EmbeddedSdk.authenticate()
, we must Authorize With Okta.
Authorize With Okta​
Using an SDK​
See Okta's Developer Site for the latest Android SDKs or Widgets. This guide uses the Okta OIDC Android SDK.
Note: At this time, the authorization flow cannot be completed using the SDK, so we recommend using the Web; The SDK is not designed to work with a secondary IdP.
Using the Web​
The library follows the best practices set out in RFC 8252 - OAuth 2.0 for Native Apps, including using Custom Tabs for authorization requests. For this reason, WebView
is explicitly not supported due to usability and security reasons.
- Step 1: Configuring the Authenticator Config
Make sure the Authenticator Config in the Beyond Identity Console is set to type Embedded
and that the Invoke URL points to your application with either an App Scheme or a Universal Link. Note: You may want to use a separate scheme for Beyond Identity and Okta.
- Step 2: Okta Authorize URL
To start the authorization flow, build a CustomTabsIntent
, and launch the OAuth2 Authorization Request URL provided by Okta.
val builder = CustomTabsIntent.Builder()
...
builder.build().launchUrl(context, OKTA_URL)
- Step 3: Invoke URL
A URL with the Invoke URL scheme should be triggered by the web page. The Android OS will look for an appropraite Activity to handle the Intent. In your Activity
, which handles your Beyond Identity scheme, override onCreate
&/ onNewIntent
, and call EmbeddedSdk.authenticate()
. You can confirm the validity of the URL with EmbeddedSdk.isAuthenticateUrl()
.
intent?.data?.let { uri ->
when {
EmbeddedSdk.isAuthenticateUrl(uri.toString()) -> {
EmbeddedSdk.authenticate(
url = uri.toString(),
passkeyId = selectedPasskeyId,
) {
...
}
}
...
}
}
- Step 4: Redirect URL
To complete the authorization flow, build another CustomTabsIntent
, and launch the redirectUrl
returned from a successful AuthenticateResponse
to complete the initial OAuth flow. Another url will be returned that contains an authorization code that can be used to exhange for an ID token using Okta's token endpoint.
intent?.data?.let { uri ->
when {
EmbeddedSdk.isAuthenticateUrl(uri.toString()) -> {
EmbeddedSdk.authenticate(
url = uri.toString(),
passkeyId = selectedPasskeyId,
) { result ->
result.onSuccess { authenticateResponse ->
authenticateResponse.redirectUrl?.let { redirectUrl ->
CustomTabsIntent.Builder().build().launchUrl(context, Uri.parse(redirectUrl))
}
}
}
}
uri.scheme == CALLBACK_URL_SCHEME -> {
// This URL contains authorization code and state parameters
// Exchange the authorization code for an id_token using Okta's token endpoint.
}
...
}
}
Full Example​
private fun launchOkta(context: Context, url: Uri = OKTA_URL) {
CustomTabsIntent.Builder().build().launchUrl(context, url)
}
private fun handleIntent(context: Context, intent: Intent?) {
selectPasskeyId { selectedPasskeyId ->
intent?.data?.let { uri ->
when {
EmbeddedSdk.isAuthenticateUrl(uri.toString()) -> {
EmbeddedSdk.authenticate(
url = uri.toString(),
passkeyId = selectedPasskeyId,
) { result ->
result.onSuccess { authenticateResponse ->
authenticateResponse.redirectUrl?.let { redirectUrl ->
CustomTabsIntent.Builder().build().launchUrl(context, Uri.parse(redirectUrl))
}
}
}
}
uri.scheme == CALLBACK_URL_SCHEME -> {
// This URL contains authorization code and state parameters
// Exchange the authorization code for an id_token using Okta's token endpoint.
}
}
}
}
}
private fun selectPasskeyId(callback: (String) -> Unit) {
// Where you can perform some logic here to select a passkey, or
// present UI to a user to enable them to select a passkey.
}