Security · FAPI · Redirect

Opening the Authorization Redirect 4 min read

After you submit a /par request, you construct the authorization URL and send the customer to the LFI's Authorization Endpoint to authenticate and authorise the consent. How your application opens that URL is security-critical — get it wrong and you break app-to-app redirection or expose the customer to credential theft.

01 What you are opening

The authorization URL built from the /par response

The API Hub returns a request_uri from your PAR request. You combine it with the LFI's authorization_endpoint (read from .well-known/openid-configuration) to build the redirect URL:

Authorization URL
https://auth1.altareq1.sandbox.apihub.openfinance.ae/auth?client_id={clientId}&response_type=code&request_uri={request_uri}

This URL is a stable, publicly accessible HTTPS endpoint owned by the LFI. On mobile it is configured as a verified deep link, so opening it correctly can hand the customer straight into the LFI's banking app. The guidance below covers how to open it from within your app; once the customer finishes at the LFI, they are redirected back to your redirect_uri — see Handling Authorization Callbacks.

02 Opening from within a mobile app

Prefer an external user-agent, then fall back

When your customer is inside your native app and you need to open the authorization redirect, you MUST open it in an external user-agent — never an embedded WebView. Two launch modes satisfy this, and you SHOULD try them in order:

  1. External application mode (preferred). Hand the URL to the operating system. Where the LFI's mobile banking app is installed and the URL is a verified Universal Link (iOS) or App Link (Android), the OS opens that app directly — this is app-to-app redirection. If the app is not installed, the OS opens the device's system browser. Both are compliant external user-agents.
  2. Platform default mode (fallback). If the external-application launch throws or returns false, catch the error and retry in platform-default mode. For https URLs this resolves to an in-app browser tab — Chrome Custom Tabs on Android, SFSafariViewController on iOS — which is still an acceptable external user-agent.
Why this order

External-application mode is tried first because it is the only mode that can hand the customer straight into the LFI's mobile banking app (app-to-app), giving the smoothest, most trusted experience. The in-app browser tab reached by platform-default mode renders the URL in a tab rather than handing off to the app, so app-to-app generally will not trigger — which is why it is the fallback, not the default.

03 Implementation

Try external-application, catch the error, fall back

The pattern is the same across native stacks: attempt to launch in external-application mode, and on failure fall back to the platform default. The example below uses Flutter's url_launcher; the same shape applies to native iOS, native Android, and React Native.

Flutter · url_launcherdart
import 'package:url_launcher/url_launcher.dart';

/// Opens an outbound Open Finance redirect URL from within the app.
Future<void> openRedirect(Uri redirectUri) async {
  try {
    // 1. Prefer an external user-agent. Where the LFI's mobile banking app is installed
    //    and the URL is a verified Universal Link / App Link, the OS opens
    //    that app directly (app-to-app). Otherwise it opens the system browser.
    final launched = await launchUrl(
      redirectUri,
      mode: LaunchMode.externalApplication,
    );
    if (!launched) {
      throw Exception('externalApplication launch returned false');
    }
  } catch (_) {
    // 2. Fall back to the platform default. For https URLs this resolves to an
    //    in-app browser tab (Chrome Custom Tabs / SFSafariViewController) —
    //    still a compliant external user-agent.
    //    NEVER fall back to LaunchMode.inAppWebView (an embedded WebView).
    await launchUrl(
      redirectUri,
      mode: LaunchMode.platformDefault,
    );
  }
}
PlatformExternal application (try first)Platform default / in-app tab (fallback)
iOSUIApplication.open(_:)SFSafariViewController
AndroidIntent.ACTION_VIEW to the system defaultChrome Custom Tabs
FlutterLaunchMode.externalApplicationLaunchMode.platformDefault
04 Prohibited

Never use an embedded WebView

The redirect MUST NOT be opened in an embedded WebView (for example WKWebView, Android WebView, or LaunchMode.inAppWebView). This is a hard requirement of RFC 8252 (OAuth 2.0 for Native Apps), which the FAPI security profile and UAE Open Finance are built on.

Embedded WebViews are forbidden for authorization

A host app can read everything inside its own embedded WebView — entered credentials, cookies, and session tokens. Embedded WebViews also break verified deep linking, so app-to-app redirection cannot occur and the customer is forced to re-authenticate from scratch. If a launch fails, fall back to the in-app browser tab (platform-default mode) — never to an embedded WebView.

05 Opening the link outside a mobile app

Web and desktop: full-page redirect, never an iframe

If your app runs in a web browser instead of as a native mobile app — on desktop or mobile web — opening the redirect is simpler. Send the customer to the LFI's Authorization Endpoint with a normal full-page browser redirect.

Full-page redirecttypescript
// Browser-based web app — top-level, full-page navigation.
// authorizationUrl = authorization_endpoint + client_id, response_type, request_uri
window.location.assign(authorizationUrl)

// Server-side equivalent (e.g. Express):
// res.redirect(303, authorizationUrl)
  • Navigate the whole pagewindow.location.assign(url) client-side, or a 302/303 from your server. The customer sees the LFI's real domain in the address bar, a key anti-phishing signal.
  • Never render the LFI's authorization or authentication screens in an <iframe> or embedded frame (including hidden iframes). This is the web equivalent of the embedded-WebView prohibition — the same RFC 8252 / FAPI rationale, plus clickjacking — and the LFI sends frame-busting headers that will block it regardless.
  • Avoid popups and new tabs or windows — popup blockers, lost address-bar visibility, and poor mobile-web behaviour make same-tab redirection the reliable choice.
  • Preserve state and the PKCE code_verifier in server-side session or secure storage so they survive the round-trip.

On desktop, handing the customer to a mobile app is the LFI's responsibility once they land on the Authorization Endpoint — via QR scan, push-to-app, or browser-based authentication. Your job is only the full-page redirect. See Authorization Endpoint — Desktop browser behaviour.

Aligned with UK Open Banking

UK Open Banking's redirection model is always domain-to-domain and full-page — an inbound screen (TPP domain → LFI domain) and an outbound screen (LFI domain → TPP domain) — which explicitly excludes iframes and embedded webviews. Desktop customers who need a mobile app are served by decoupled / QR-code hand-off, driven by the LFI. The rule for the TPP is the same in both cases: redirect the full page and let the LFI drive the hand-off.