OAuth
Akoya uses the OAuth2/OIDC style. Outlined below are various approaches for device/app integration.
Do not use insecure web containers
In the get authorization code step outlined in each of the methods detailed below, the URL should be launched from within a browser or a secure web container such as SFSafariViewController or Chrome Custom Tabs. This URL should not be launched within insecure containers that allow the mobile app to intercept user input and thus intercept user credentials.
Website/WebApp
Popup Approach (recommended)
In this flow you’re kicking off the consumer consent OAuth via a popup window.
Steps:
-
User selects the data provider they’d like to connect (drop down, button, link,…)
-
Instruct the browser to open a popup window using the request URL as outlined here: Get authorization code
-
The user logs in, agrees to terms and conditions, selects accounts
-
Akoya redirects to a page you host with the authorization grant code
-
Your server exchanges the grant code for the ID token: Token
-
Your server completes the request and returns JavaScript telling the browser to close the popup window
Full Redirect (no popup) Approach
In this flow you’re redirecting the user’s current page (your website/web app) to the consumer consent OAuth.
Steps:
-
User selects the provider they’d like to connect (drop down, button, link,…)
-
Instruct the browser to redirect the current page (your app) to the request URL as outlined here: Get authorization code
-
The user logs in, agrees to terms and conditions, selects accounts
-
Akoya redirects to a page you host with the authorization grant code
-
Your server exchanges the grant code for the ID token: Token
-
Your server completes the request and lets the user know they are now connected
Mobile App
The industry standard approach is known as deep linking. This is a technique for your app to open the mobile browser, ask the user to authenticate, then your redirect URL links directly back to your app, having it regain focus.
Steps:
-
User selects the provider they’d like to connect (drop down, button, link,…)
-
Instruct the app to open the browser to the request URL as outlined here: Get authorization code
-
The user logs in, agrees to terms and conditions, selects accounts
-
Akoya redirects to a deep link (see below, option A) you’ve setup with the authorization grant code
-
Your app exchanges the grant code for the ID token: Token
-
Your app is now ready to pull data
This approach has two different styles (option A or option B), your redirect can either be page on your server (option B) which will then handle a redirect to the deep link you’ve setup. Or (option A) your redirect goes directly back to the app, and your app handles the token exchange.
iOS
Setting up your deep link schema:
You’ll want to review: Apple Developer Documentation - Defining a Custom URL Scheme for Your App
-
In the URL Schemes box, specify the prefix you use for your URLs.
-
Choose a role for your app: either an editor role for URL schemes you define, or a viewer role for schemes your app adopts but doesn’t define.
-
Specify an identifier for your app.
The identifier you supply with your scheme distinguishes your app from others that declare support for the same scheme. To ensure uniqueness, specify a reverse DNS string that incorporates your company’s domain and app name.
Example code handling universal link:
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool
{
// Get URL components from the incoming user activity.
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else {
return false
}
// Check for specific URL components that you need.
guard let path = components.path,
let params = components.queryItems else {
return false
}
if let authCode = params.first(where: { $0.name == "code" } )?.value,
//send code to your server to exchange for an id token
//https://docs.akoya.com/reference/get-token
return true
} else {
//invalid redirect
return false
}
}
Android
Setting up your deep link schema:
Start by reviewing: Android Developers Documentation - Create Deep Links to App Content
To create a link to your app content, add an intent filter that contains these elements and attribute values in your manifest:
<action>
Specify the ACTION_VIEW
intent action so that the intent filter can be reached from Google Search. <data>
Add one or more <data>
tags, each of which represents a URI format that resolves to the activity. At minimum, the <data>
tag must include the android:scheme
attribute.
You can add more attributes to further refine the type of URI that the activity accepts. For example, you might have multiple activities that accept similar URIs but which differ simply based on the path name. In this case, use the android:path
attribute or its pathPattern
or pathPrefix
variants to differentiate which activity the system should open for different URI paths.
<category>
Include the BROWSABLE
category. It is required in order for the intent filter to be accessible from a web browser. Without it, clicking a link in a browser cannot resolve to your app.
Also include the DEFAULT
category. This allows your app to respond to implicit intents. Without this, the activity can be started only if the intent specifies your app component name.
The following XML snippet shows how you might specify an intent filter in your manifest for deep linking. The URIs “example://gizmos”
and “<http://www.example.com/gizmos”
> both resolve to this activity.
<activity
android:name="com.example.android.GizmosActivity"
android:label="@string/title_gizmos" >
<intent-filter android:label="@string/filter_view_http_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "http://www.example.com/gizmos” -->
<data android:scheme="http"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
<!-- note that the leading "/" is required for pathPrefix-->
</intent-filter>
<intent-filter android:label="@string/filter_view_example_gizmos">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "example://gizmos” -->
<data android:scheme="example"
android:host="gizmos" />
</intent-filter>
</activity>
Notice that the two intent filters only differ by the <data>
element. Although it's possible to include multiple <data>
elements in the same filter, it's important that you create separate filters when your intention is to declare unique URLs (such as a specific combination of scheme
and host
), because multiple <data>
elements in the same intent filter are actually merged together to account for all variations of their combined attributes. For example, consider the following:
<intent-filter>
...
<data android:scheme="https" android:host="www.example.com" />
<data android:scheme="app" android:host="open.my.app" />
</intent-filter>
It might seem as though this supports only <https://www.example.com
> and app://open.my.app
. However, it actually supports those two, plus these: app://www.example.com
and <https://open.my.app
>.
Once you've added intent filters with URIs for activity content to your app manifest, Android is able to route any Intent
that has matching URIs to your app at runtime.
Example code to read from the redirect:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = getIntent();
Uri data = intent.getData();
String code = uri.getQueryParameter("code");
//use code to call your server and exchange token
// https://docs.akoya.com/reference/get-token
}
Desktop App
Functions basically identically to mobile (see above), here are some starting points to get your schema for deep linking setup.
Windows
Start with the protocol declaration.
Here’s the XML the protocol declaration generated:
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="com.myapp.callback" />
</uap:Extension>
Handling the redirect:
protected override void OnActivated(IActivatedEventArgs args)
{
Frame rootFrame = CreateRootFrame();
if (args.Kind == ActivationKind.Protocol)
{
var protocolArgs = args as ProtocolActivatedEventArgs;
rootFrame.Navigate(typeof(ProtocolActivationPage), protocolArgs.Uri);
}
else
{
rootFrame.Navigate(typeof(MainPage));
}
// Ensure the current window is active
Window.Current.Activate();
}
The app simply uses the Launcher.LaunchUriAsync API to deep link into the app. Here’s what that code might look like:
Uri uri = new Uri("com.myapp.callback:?code=1234");
await Launcher.LaunchUriAsync(uri);
Review the following for more information:
App Integration - Linking and Integrating Apps on Windows 10
macOS
Review: Apple Developer Documentation
Clients craft URLs based on your scheme and ask your app to open them by calling the open(_:options:completionHandler:)
method of UIApplication
. Clients can ask the system to inform them when your app opens the URL.
let url = URL(string: "myapp:callback")
UIApplication.shared.open(url!) {
(result) in
if result {
// The URL was delivered successfully!
}}
Registering you schema is the same as mobile if you’re using scenes Apple Developer Documentation see above in mobile for more details.
Updated almost 2 years ago