Skip to content

Commit 3cf65da

Browse files
susanharper-oktaannejuan-okta
authored andcommitted
Native to Web SSO (#5868)
* initial updates * formatting from the google * native to web sso * ready for review * review comments * local review fixes * more review comments * editorial review:
1 parent 193e71f commit 3cf65da

4 files changed

Lines changed: 285 additions & 0 deletions

File tree

packages/@okta/vuepress-site/docs/guides/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ guides:
7171
- mobile-idx-sdk-overview
7272
- multiple-identifiers
7373
- mobile-swift-configure-redirect
74+
- native-to-web-sso
7475
- scim-provisioning-integration-overview
7576
- scim-provisioning-integration-prepare
7677
- scim-provisioning-integration-connect
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: Configure Native to Web SSO
3+
excerpt: Learn what Native to Web SSO is and how to use it
4+
layout: Guides
5+
sections:
6+
- main
7+
---
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
---
2+
title: Configure Native to Web SSO
3+
excerpt: Learn what Native to Web SSO is and how to use it
4+
layout: Guides
5+
---
6+
7+
<ApiLifecycle access="ea" />
8+
9+
Learn what Native to Web SSO is, why it matters, and how it actually connects your OpenID Connect (OIDC) apps to your web-based services.
10+
11+
---
12+
13+
#### Learning outcomes
14+
15+
* Understand the native to web SSO flow.
16+
* Set up your allowlist for token exchange.
17+
* Manage your allowlist.
18+
19+
#### What you need
20+
21+
* [Okta Integrator Free Plan org](https://developer.okta.com/signup)
22+
* An OIDC app that you want to use as the origin app. Okta supports web, SPA, and native OIDC apps.
23+
* An OIDC or SAML app that you want to use as the target web app
24+
25+
---
26+
27+
## Overview
28+
29+
Native to Web SSO creates a seamless, unified authentication experience when a user transitions from an OIDC origin app (like a native app) to a web app (either OIDC or SAML). It’s a one-way trust from the origin app to the target.
30+
31+
Native to Web SSO achieves this by exchanging a token with the `interclient_access` scope for a one-time token. This token is used to bootstrap an authentication into the target OIDC or SAML app using authentication information such as previous factor verifications from a session created when obtaining the original token. This eliminates repeated sign-in prompts and simplifies development by reducing authentication complexity.
32+
33+
### Handle different assurance levels and remediation
34+
35+
Sometimes the target web app has stricter security needs than the requesting app. For instance, the original app may have only required a username and password, but the target web app requires a second factor, like a one-time passcode (OTP).
36+
37+
Okta handles that during the transition by prompting the user to satisfy the missing requirement. The user sees a single prompt for the complimentary factor (OTP), not a full authentication restart.
38+
39+
### Common use cases
40+
41+
* **Incorporating SaaS**: You have an app, and you want to seamlessly incorporate a third-party SaaS app into it.
42+
* **The application dashboard**: Your app acts as an "application dashboard" with links to multiple web apps.
43+
* **Modernization**: You’re going through a large modernization project. This pattern lets your legacy apps continue to operate unmodified while you update the new parts of the system. This is especially helpful when you want to move towards a modern native app and incorporate the legacy web (hybrid native/web) app.
44+
* **Integration limitations**: It’s critical when you can’t modify the target app integration to accommodate a special connection. The target source code isn’t accessible, but it already supports federation.
45+
46+
In all these cases, the Identity and Access Management (IAM) platform becomes the secure fabric that seamlessly weaves all of your apps together into one low-friction experience.
47+
48+
## Native to Web SSO flow
49+
50+
<div class="three-quarter">
51+
52+
![Sequence diagram that displays the interaction between the user, OIDC origin app, authorization server, and target web app for Native to Web SSO](/img/native-to-web-sso.png)
53+
54+
</div>
55+
56+
<!-- Generated using http://www.plantuml.com/plantuml/uml/
57+
58+
@startuml
59+
skinparam monochrome true
60+
actor "User" as user
61+
participant "Origin OIDC App" as oidcapp
62+
participant "Authorization Server (Okta)" as okta
63+
participant "Target Web App" as webapp
64+
65+
autonumber "<b>#."
66+
user -> oidcapp: Signs in to OIDC app
67+
oidcapp -> okta: Sends direct auth request for tokens with interclient_access scope
68+
okta -> okta: Creates backend-only session
69+
okta -> oidcapp: Returns tokens
70+
user -> oidcapp: Requests to access resource from target app
71+
oidcapp -> okta: Requests access token refresh
72+
okta -> oidcapp: Sends new tokens back
73+
oidcapp -> okta: Sends request to exchange access/ID tokens for interclient token
74+
okta -> oidcapp: Validates trust relationship, user assigned to app, returns interclient token
75+
oidcapp -> webapp: Redirects to web app
76+
webapp -> okta: Receives token, sends authentication request
77+
okta -> okta: Validates, loads the state, bootstraps state token, evaluates target app policy
78+
okta -> webapp: Policy conditions are met, user is signed in
79+
@enduml
80+
81+
-->
82+
83+
The flow steps:
84+
85+
1. The user signs in to an OpenID Connect (OIDC) origin app.
86+
2. The app obtains tokens through a request to the `/token` endpoint. The request includes the `interclient_access` and `offline_access` (optional) scopes.
87+
3. Okta checks that the app is an admin-configured trusted app that’s allowed to use this flow. Then, it creates a special backend-only session. This session tracks the user’s authentication level and security assurances, such as, "This user verified their identity with a strong factor on a trusted device."
88+
4. Okta sends back the access token, the session-bound ID token, and a refresh token if `offline_access` was requested.
89+
5. The user requests access to a resource from the target web app (client app).
90+
6. The OIDC origin app now needs to launch the other app. It makes a request to [refresh the access token](/docs/guides/refresh-tokens/main/#use-a-refresh-token), if necessary.
91+
7. Okta sends back the new tokens, and the refresh token (if requested).
92+
8. The app then makes a request to the `/token` endpoint to exchange the access and ID tokens for a single-use `interclient_token`. This token is requested using the `requested_token_type` (`urn:okta:params:oauth:token-type:interclient_token`) and the Token Exchange grant type (`urn:ietf:params:oauth:grant-type:token-exchange`).
93+
9. Okta validates the trust relationship and user assignment of the target web app, and returns the single-use `interclient_token` that’s bound to the assurance of the `id_token` and target app. This single-use token is the user’s ticket to the target web app.
94+
10. The OIDC app launches the authorization server URI with intent for the target web app, securely passing the `interclient_token` to it.
95+
11. The web app receives the token and sends it to Okta in an authentication request (`/authorize` or `/sso/saml`).
96+
12. Okta validates the `interclient_token`, `audience`, target app ID, issuer, and so on.
97+
98+
* **Look up context**: Okta looks up the associated backend session.
99+
* **Loads the state**: Okta then reconstructs the user’s state. This tells Okta who the user is and what security assurances (MFA, Device Trust, and so on) were already satisfied when they signed in to the OIDC origin app.
100+
* **Bootstraps the state token to the flow**: Rather than making the user start from a blank sign-in page, Okta uses this loaded context to bootstrap a new state token for the web app's policy evaluation.
101+
102+
13. Okta checks if the user has satisfied all of the target web app’s policy requirements. If all checks pass, the user is immediately signed in, otherwise the user is prompted to satisfy all policy requirements.
103+
104+
> **Note**: The user isn’t allowed to cancel and switch users.
105+
106+
## Configure the app
107+
108+
The OIDC origin app exchanges access and ID tokens for a single-use interclient token from the target web app. To do this, use the Token Exchange grant type in the exchange request.
109+
110+
To update the app that you want to request single-use interclient tokens, use the [Replace an app](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/Application/#tag/Application/operation/replaceApplication!path=4/settings/oauthClient&t=request) method.
111+
112+
In the `oauthClient` object of your PUT request, add the `urn:ietf:params:oauth:grant-type:token-exchange` value to the `grant_types` array.
113+
114+
**Request example**
115+
116+
This example request is truncated for brevity.
117+
118+
```JSON
119+
{
120+
"oauthClient": {
121+
. . .
122+
"grant_types": [
123+
"authorization_code,"
124+
"urn:ietf:params:oauth:grant-type:token-exchange"
125+
],
126+
. . .
127+
}
128+
}
129+
```
130+
131+
## Configure the trust map
132+
133+
Define a list of apps that are allowed to request the single-use interclient token on the target web app. This allowlist is a trust map between the origin app and the target web app. It ensures that the SSO flow only happens between apps that you explicitly trust. You can define up to five trusted apps per target web app.
134+
135+
Okta checks this trusted relationship at two critical points in the flow:
136+
137+
* **During authentication**: The OIDC origin app can only request the special `interclient_access` scope if it has a trust relationship set up.
138+
139+
* **During token exchange**: When the OIDC origin app asks for the `interclient_token`, Okta explicitly checks to ensure that the app is on the target app's allowed list. If it's not there, the token exchange is denied.
140+
141+
To create an allowlist of apps, use the [Create an allowed app mapping for a target app](http://localhost:3000/openapi/okta-management/management/tag/ApplicationInterclientTrustMappings/#tag/ApplicationInterclientTrustMappings/operation/createInterclientTrustMapping) method (`POST /api/v1/apps/{appId}/interclient-allowed-apps`). The `appID` is the target app’s ID.
142+
143+
> **Note**: You can also use the [Admin Console](https://help.okta.com/okta_help.htm?type=oie&id=apps-native-to-web) to configure the trust mapping.
144+
145+
In the body of the request, include the [app ID](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/Application/#tag/Application/operation/listApplications!c=200&path=4/id&t=response) of the app that you want to add to the allowlist:
146+
147+
```JSON
148+
{
149+
"id": "{appId}"
150+
}
151+
```
152+
153+
**Response example**
154+
155+
```JSON
156+
{
157+
"id": "itm8vef5ul1nLwiJe0g7",
158+
"orgId": "00o47ijbqfgnq5gj00g7",
159+
"appInstanceId": "{targetwebappID}",
160+
"trustedAppInstanceId": "{OIDCappID}",
161+
"created": "2025-11-12T23:17:09.000Z",
162+
"lastUpdated": "2025-11-12T23:17:09.000Z",
163+
"lastUpdatedBy": "00u47ijy7sRLaeSdC0g7"
164+
}
165+
```
166+
167+
### Application Interclient Trust Mappings API
168+
169+
See the following new [Application Interclient Trust Mappings API](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/ApplicationInterclientTrustMappings/) endpoints to perform other Native to Web SSO tasks:
170+
171+
* To get a list of allowed apps for a target app, use the [List all allowed apps for a target app](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/ApplicationInterclientTrustMappings/#tag/ApplicationInterclientTrustMappings/operation/listInterclientAllowedApplications) method (`GET https://{yourOktaDomain}/api/v1/apps/{appId}/interclient-allowed-apps`). The `appId` is the ID of the target web app (the one allowing the SSO).
172+
173+
* To get a list of target apps that allow an app to SSO, use the [List all target apps for an allowed app](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/ApplicationInterclientTrustMappings/#tag/ApplicationInterclientTrustMappings/operation/listInterclientTargetApplications) method (`GET https://{yourOktaDomain}/api/v1/apps/{appId}/interclient-target-apps`). The `appId` is the ID of the requesting OIDC origin app (the one allowed to request the SSO).
174+
175+
* To delete a trust mapping, use the [Delete an interclient trust mapping](https://developer.okta.com/docs/api/openapi/okta-management/management/tag/ApplicationInterclientTrustMappings/#tag/ApplicationInterclientTrustMappings/operation/deleteInterclientTrustMapping) method.
176+
177+
### Scopes
178+
179+
There are two new OAuth 2.0 scopes available for the interclient endpoints:
180+
181+
* `okta.apps.interclientTrust.manage`: Use to create a resource, manage a resource, or delete a resource
182+
* `okta.apps.interclientTrust.read`: Use to read information about a resource
183+
184+
## Flow specifics
185+
186+
The following section outlines the requests required to perform Native to Web SSO. These example requests use a native app as the origin app. You can obtain a token with the `interclient_access` scope using your preferred [authentication method](/docs/guides/implement-grant-type/authcode/main/). The examples below use Resource Owner Password as the authentication flow for simplicity.
187+
188+
### Request for initial tokens
189+
190+
Before you can begin this flow, collect the required credentials from the user in a manner of your choosing. Then, make a single API call to the Okta authorization server `/token` endpoint. Your request should look something like the following example:
191+
192+
```BASH
193+
curl --request POST \
194+
--url https://{yourOktaDomain}/oauth2/v1/token \
195+
--header 'accept: application/json' \
196+
--header 'authorization: Basic MG9hYn...' \
197+
--header 'content-type: application/x-www-form-urlencoded' \
198+
--data 'grant_type=password
199+
&client_id={client_id}
200+
&username=testuser1%40example.com
201+
&password=%7CmCovrlnU9oZU4qWGrhQSM%3Dyd
202+
&scope=openid%20offline_access%20interclient_access'
203+
```
204+
205+
Note the parameters that are passed:
206+
207+
* `client_id`: Matches the client ID of the OIDC origin app. You can find it at the top of your app's **General** tab
208+
* `scope`: Must be `openid`, `interclient_access`, and optionally `offline_access`
209+
* `grant_type`: `password`, which indicates that you're using the Resource Owner Password grant type.
210+
* `username`: The username of a user registered with Okta.
211+
* `password`: The password of a user registered with Okta.
212+
213+
> **Note**: For more information on these parameters, see the `/token` [endpoint](https://developer.okta.com/docs/api/openapi/okta-oauth/oauth/tag/OrgAS/#tag/OrgAS/operation/token).
214+
215+
**Response example**
216+
217+
If the credentials are valid, Okta responds with the required tokens. This example response is truncated for brevity.
218+
219+
```JSON
220+
{
221+
"token_type": "Bearer",
222+
"expires_in": 3600,
223+
"access_token": "eyJraWQiOiItbkk . . . aIRQ",
224+
"scope": "openid offline_access interclient_access",
225+
"refresh_token": "DnZ77s5coFFJsj7CBO5NJU_wlZs0SZ0euCeiKXrN8T4",
226+
"id_token": "eyJraWQi . . . AHlwNmdw"
227+
}
228+
```
229+
230+
### Request to initialize Native to Web SSO
231+
232+
When the user requests access to a resource from the target web app, the native app needs to launch a trusted target web app. It makes a request to refresh the access token, if necessary, and gets back refreshed tokens from Okta. Then, the OIDC origin app needs to exchange the tokens for a single-use interclient token. Your request should look something like this example. The tokens are truncated for brevity.
233+
234+
**Request example**
235+
236+
```BASH
237+
curl --request POST
238+
--url https://{yourOktaDomain}/oauth2/v1/token \
239+
--header 'content-type: application/x-www-form-urlencoded' \
240+
--header 'accept: application/json' \
241+
--data 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange
242+
&client_id={client_id}
243+
&actor_token=eyJra. . . tSXL-HCA
244+
&actor_token_type=urn:ietf:params:oauth:token-type:access_token
245+
&subject_token=eyJr. . .cbYGw
246+
&subject_token_type=urn:ietf:params:oauth:token-type:id_token
247+
&requested_token_type=urn:okta:params:oauth:token-type:interclient_token
248+
&audience=urn:okta:apps:0oa8vcy7h1eyj7wLL0g7'
249+
```
250+
251+
Note the parameters that are passed:
252+
253+
* `client_id`: Matches the client ID of the OIDC origin app. You can find it at the top of your app's **General** tab
254+
* `actor_token`: The value of the access token that you obtained in the last request
255+
* `actor_token_type`: `urn:ietf:params:oauth:token-type:access_token`
256+
* `subject_token`: A security token that represents the identity of the party on behalf of whom the request is being made, which is the value of the ID token that you obtained in the last request.
257+
* `subject_token_type`: `urn:ietf:params:oauth:token-type:id_token`
258+
* `requested_token_type`: The type of token that you’re requesting in exchange for the `actor_token` and `subject_token`. (`urn:okta:params:oauth:token-type:interclient_token`)
259+
* `audience`: The target audience for the requested token bound to the target app using the IdP/Okta application/client ID (`urn:okta:apps:{target web app client_id}`)
260+
* `grant_type`: `urn:ietf:params:oauth:grant-type:token-exchange`
261+
262+
**Response example**
263+
264+
This example response is truncated for brevity.
265+
266+
```JSON
267+
{
268+
"token_type": "N_A",
269+
"expires_in": 300,
270+
"access_token": "eyJraWQiOiJNTG. . .GubhhEsg",
271+
"issued_token_type": "urn:okta:params:oauth:token-type:interclient_token"
272+
}
273+
```

packages/@okta/vuepress-theme-prose/const/navbar.const.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,10 @@ export const guides = [
586586
title: "Configure SSO for native apps",
587587
guideName: "configure-native-sso",
588588
},
589+
{
590+
title: "Configure Native to Web SSO",
591+
guideName: "native-to-web-sso",
592+
},
589593
{
590594
title: "Manage credentials using the Okta Client SDK",
591595
guideName: "manage-user-creds",

0 commit comments

Comments
 (0)