Skip to content

Commit ad8209c

Browse files
authored
Update guide-integrate-sca.mdx (#379)
1 parent fcf9601 commit ad8209c

File tree

1 file changed

+63
-99
lines changed

1 file changed

+63
-99
lines changed

docs/topics/users/consent/guide-integrate-sca.mdx

Lines changed: 63 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ To integrate Swan's Strong Customer Authentication (SCA), you'll need:
1818

1919
1. An in-app browser package.
2020
1. A custom URL scheme with a deep link listener package.
21-
1. A backend server (this guide uses `https://awesome-api.com`).
21+
1. A backend server (this guide uses `https://my-company-api.com`).
2222

2323
Check out [Swan's demo app GitHub repository](https://github.com/swan-io/swan-partner-mobile) for an integration example.
2424

@@ -31,11 +31,7 @@ Use the documentation for your system's recommended API to set up your in-app br
3131
| Android | [Custom Tabs API](https://developer.android.com/jetpack/androidx/releases/browser) | [Swan implementation](https://github.com/swan-io/react-native-browser/blob/main/android/src/main/java/io/swan/rnbrowser/RNSwanBrowserModuleImpl.java) |
3232
| iOS | [SFSafariViewController API](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) | [Swan implementation](https://github.com/swan-io/react-native-browser/blob/main/ios/RNSwanBrowser.mm) |
3333

34-
There are also several wrappers available for these APIs:
35-
36-
- Swan's official package: [@swan-io/react-native-browser](https://github.com/swan-io/react-native-browser)
37-
- [@capacitor/browser](https://capacitorjs.com/docs/apis/browser)
38-
- [flutter_inappwebview ChromeSafariBrowser](https://inappwebview.dev/docs/in-app-browsers/chrome-safari-browser)
34+
We provide an official React Native package: [@swan-io/react-native-browser](https://github.com/swan-io/react-native-browser)
3935

4036
:::warning Follow the references
4137
When using frameworks other than React Native, ensure that your package is configured in a way that follows Swan's implementation references.
@@ -50,55 +46,27 @@ Use the documentation for your system's recommended tutorial to set up the deep
5046
| Android | [Create deep links to app content](https://developer.android.com/training/app-links/deep-linking) |
5147
| iOS | [Defining a custom URL scheme for your app](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) |
5248

53-
There are also several guides available to listen for deep link configuration:
54-
55-
- [React Native](https://reactnative.dev/docs/linking)
56-
- [Flutter](https://docs.flutter.dev/development/ui/navigation/deep-linking)
57-
- [Capacitor](https://capacitorjs.com/docs/apis/app#addlistenerappurlopen-)
49+
If you are using React Native, follow [this guide](https://reactnative.dev/docs/linking).
5850

5951
## Step 3: Configure the sign-in process {#configure-signin}
6052

6153
This five-step process describes an ideal path for your users to sign in.
6254

63-
:::info Using Swan's react-native-browser package
64-
Swan's `react-native-browser` takes care of listening to the deep link event.
65-
Please **ignore the `listener` declarations** in steps 3.1, 3.5, and 4.3.
66-
67-
Instead, use the following **`onClose` option** instead:
68-
69-
```js
70-
import { openBrowser } from "@swan-io/react-native-browser";
71-
72-
const onAction = () => {
73-
// not needed with @swan-io/react-native-browser
74-
// const listener = Linking.addListener("url", ({ url }) => {});
75-
76-
openBrowser("https://awesome-api.com/endpoint", {
77-
onClose: (url) => {
78-
// fired on browser closed
79-
// url will be defined if the browser has been closed via deeplink
80-
},
81-
});
82-
};
83-
```
84-
85-
:::
86-
8755
### 3.1 Sign-in button {#configure-signin-button}
8856

8957
First, the user clicks a sign-in button in your app.
9058
Clicking this button opens an in-app browser and starts listening for deep links.
9159

9260
```js showLineNumbers
93-
const onSignInWithSwanButtonPress = () => {
94-
const listener = Linking.addListener("url", ({ url }) => {
95-
// called when deep link is visited
96-
});
61+
Linking.addListener("url", ({ url }) => {
62+
// called when deep link is visited
63+
});
9764

98-
InAppBrowser.open("https://awesome-api.com/auth", {
99-
onClose: () => listener.remove(), // executed when the browser is closed
100-
});
101-
};
65+
//
66+
67+
openBrowser("https://my-company-api.com/auth").catch((error) => {
68+
console.error(error);
69+
});
10270
```
10371

10472
### 3.2 Authorization URL {#configure-signin-url}
@@ -110,7 +78,7 @@ app.get("/auth", async (req, reply) => {
11078
const params = querystring.encode({
11179
client_id: "$YOUR_CLIENT_ID",
11280
response_type: "code",
113-
redirect_uri: "https://awesome-api.com/auth/callback", // must be registered in our dashboard
81+
redirect_uri: "https://my-company-api.com/auth/callback", // must be registered in our dashboard
11482
scope: ["openid", "offline"].join(" "),
11583
state: generateUserState(req),
11684
});
@@ -121,7 +89,7 @@ app.get("/auth", async (req, reply) => {
12189

12290
### 3.3 User logs in {#configure-signin-login}
12391

124-
The user logs in and is redirected to https://awesome-api.com/auth/callback.
92+
The user logs in and is redirected to https://my-company-api.com/auth/callback.
12593

12694
### 3.4 Server responds {#configure-signin-server}
12795

@@ -143,15 +111,13 @@ app.get("/auth/callback", async (req, reply) => {
143111
client_secret: "$YOUR_CLIENT_SECRET",
144112
grant_type: "authorization_code",
145113
code: req.query.code,
146-
redirect_uri: "https://awesome-api.com/auth/callback",
114+
redirect_uri: "https://my-company-api.com/auth/callback",
147115
});
148116

149117
const sessionId = randomUUID();
150118
await storeTokenInKeyValueStore(sessionId, token);
151119

152-
return reply.redirect(
153-
`com.awesome.app://browser/close?sessionId=${sessionId}`
154-
);
120+
return reply.redirect(`com.company.myapp://close?sessionId=${sessionId}`);
155121
});
156122
```
157123

@@ -160,25 +126,25 @@ app.get("/auth/callback", async (req, reply) => {
160126
Finally, the listener closes the in-app browser and stores the identifier.
161127

162128
```js showLineNumbers
163-
const onSignInWithSwanButtonPress = () => {
164-
const listener = Linking.addListener("url", ({ url }) => {
165-
// called when deep link is visited
129+
Linking.addListener("url", ({ url }) => {
130+
// called when deep link is visited
166131

167-
if (url.startsWith("com.awesome.app://browser/close")) {
168-
InAppBrowser.close();
132+
if (url.startsWith("com.company.myapp://close")) {
133+
closeBrowser(); // required on iOS
169134

170-
const { query } = parseUrl(url);
135+
const { query } = parseUrl(url);
171136

172-
if (query.sessionId) {
173-
AsyncStorage.setItem("sessionId", query.sessionId);
174-
}
137+
if (query.sessionId) {
138+
AsyncStorage.setItem("sessionId", query.sessionId);
175139
}
176-
});
140+
}
141+
});
177142

178-
InAppBrowser.open("https://awesome-api.com/auth", {
179-
onClose: () => listener.remove(), // executed when the browser is closed
180-
});
181-
};
143+
//
144+
145+
openBrowser("https://my-company-api.com/auth").catch((error) => {
146+
console.error(error);
147+
});
182148
```
183149

184150
## Step 4: Configure the consent process {#configure-consent}
@@ -197,13 +163,11 @@ First, the user clicks a **Create a card** button in your app.
197163
Your server API receives the call with the following `sessionId` header.
198164

199165
```js showLineNumbers
200-
const onAddCardButtonPress = async () => {
201-
const sessionId = await AsyncStorage.getItem("sessionId");
166+
const sessionId = await AsyncStorage.getItem("sessionId");
202167

203-
await client.post("https://awesome-api.com/add-card", {
204-
headers: { sessionId },
205-
});
206-
};
168+
await client.post("https://my-company-api.com/add-card", {
169+
headers: { sessionId },
170+
});
207171
```
208172

209173
### 4.2 Consent URL {#configure-consent-url}
@@ -218,7 +182,7 @@ app.get("/add-card", async (req, reply) => {
218182
{
219183
input: {
220184
//
221-
consentRedirectUrl: "https://awesome-api.com/add-card/callback",
185+
consentRedirectUrl: "https://my-company-api.com/add-card/callback",
222186
},
223187
},
224188
{
@@ -237,26 +201,27 @@ app.get("/add-card", async (req, reply) => {
237201
The app opens an in-app browser and starts listening for deep links.
238202

239203
```js showLineNumbers
240-
const onAddCardButtonPress = async () => {
241-
const sessionId = await AsyncStorage.getItem("sessionId");
204+
Linking.addListener("url", ({ url }) => {
205+
// called when deep link is visited
206+
});
242207

243-
const { consentUrl } = await client.post("https://awesome-api.com/add-card", {
244-
headers: { sessionId },
245-
});
208+
//
246209

247-
const listener = Linking.addListener("url", ({ url }) => {
248-
// called when deep link is visited
249-
});
210+
const sessionId = await AsyncStorage.getItem("sessionId");
250211

251-
InAppBrowser.open(consentUrl, {
252-
onClose: () => listener.remove(), // executed when the browser is closed
253-
});
254-
};
212+
const { consentUrl } = await client.post(
213+
"https://my-company-api.com/add-card",
214+
{ headers: { sessionId } }
215+
);
216+
217+
openBrowser(consentUrl).catch((error) => {
218+
console.error(error);
219+
});
255220
```
256221

257222
### 4.4 User consents {#configure-consent-user}
258223

259-
The user consents and is redirected to https://awesome-api.com/add-card/callback.
224+
The user consents and is redirected to https://my-company-api.com/add-card/callback.
260225

261226
During redirection, Swan adds these query parameters to the URL.
262227

@@ -273,7 +238,7 @@ Your server performs any necessary additional operations, then redirects the use
273238
```js showLineNumbers
274239
app.get("/add-card/callback", async (req, reply) => {
275240
// perform additional operations…
276-
return reply.redirect("com.awesome.app://browser/close");
241+
return reply.redirect("com.company.myapp://close");
277242
});
278243
```
279244

@@ -282,23 +247,22 @@ app.get("/add-card/callback", async (req, reply) => {
282247
Finally, the listener closes the in-app browser.
283248

284249
```js showLineNumbers
285-
const onAddCardButtonPress = async () => {
286-
const sessionId = await AsyncStorage.getItem("sessionId");
250+
Linking.addListener("url", ({ url }) => {
251+
// called when deep link is visited
287252

288-
const { consentUrl } = await client.post("https://awesome-api.com/add-card", {
289-
headers: { sessionId },
290-
});
253+
if (url.startsWith("com.company.myapp://close")) {
254+
closeBrowser(); // required on iOS
255+
}
256+
});
291257

292-
const listener = Linking.addListener("url", ({ url }) => {
293-
// called when deep link is visited
258+
const sessionId = await AsyncStorage.getItem("sessionId");
294259

295-
if (url.startsWith("com.awesome.app://browser/close")) {
296-
InAppBrowser.close();
297-
}
298-
});
260+
const { consentUrl } = await client.post(
261+
"https://my-company-api.com/add-card",
262+
{ headers: { sessionId } }
263+
);
299264

300-
InAppBrowser.open(consentUrl, {
301-
onClose: () => listener.remove(), // executed when the browser is closed
302-
});
303-
};
265+
openBrowser(consentUrl).catch((error) => {
266+
console.error(error);
267+
});
304268
```

0 commit comments

Comments
 (0)