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.

A diagram explaining the flow of a popup from an app to a login then to the bank

Steps:

  1. User selects the data provider they’d like to connect (drop down, button, link,…)

  2. Instruct the browser to open a popup window using the request URL as outlined here: Get authorization code

  3. The user logs in, agrees to terms and conditions, selects accounts

  4. Akoya redirects to a page you host with the authorization grant code

  5. Your server exchanges the grant code for the ID token: Token

  6. 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.

A diagram explaining a browser redirecting from on URL to another and then back to original URL

Steps:

  1. User selects the provider they’d like to connect (drop down, button, link,…)

  2. Instruct the browser to redirect the current page (your app) to the request URL as outlined here: Get authorization code

  3. The user logs in, agrees to terms and conditions, selects accounts

  4. Akoya redirects to a page you host with the authorization grant code

  5. Your server exchanges the grant code for the ID token: Token

  6. 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.

A diagram of mobile screen progression from App to login to either showing the user a screen to show linking or going directly back to original app

Steps:

  1. User selects the provider they’d like to connect (drop down, button, link,…)

  2. Instruct the app to open the browser to the request URL as outlined here: Get authorization code

  3. The user logs in, agrees to terms and conditions, selects accounts

  4. Akoya redirects to a deep link (see below, option A) you’ve setup with the authorization grant code

  5. Your app exchanges the grant code for the ID token: Token

  6. 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.

A screenshot showing an example of how to register the URL schema under the URL Types section

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

The desktop functions identically to the mobile app, see Mobile App. 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.LaunchΒ­UriAsync 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.