Browser
Browser wraps expo-web-browser: a page shown in an in-app browser, and a sign-in flow through
the system's own authentication session.
import { Browser } from '@ng-native/expo';
inject(Browser)Install
npx expo install expo-web-browserimport { Browser } from '@ng-native/expo/browser';The smallest thing that works
import { Component, inject } from '@angular/core';
import { Browser } from '@ng-native/expo/browser';
@Component({
selector: 'app-sign-in',
template: '<pressable (press)="signIn()"><text>Sign in</text></pressable>',
})
export class SignIn {
private readonly browser = inject(Browser);
protected async signIn(): Promise<void> {
const returned = await this.browser.signIn(
'https://id.example.com/authorize?client_id=...&redirect_uri=myapp://signed-in',
'myapp://signed-in',
);
if (returned) {
const code = new URL(returned).searchParams.get('code');
}
}
}Opening a page and signing in
open(url)shows any page in the in-app browser -SFSafariViewControlleron iOS, a Custom Tab on Android - and resolves when the person closes it. Use it for anything that is not a sign-in: a privacy policy, a receipt, an external link.signIn(url, redirectUrl)opens the system's authentication session instead -ASWebAuthenticationSessionon iOS, a Custom Tab on Android - which shares the browser's cookies (so an existing session is picked up) and closes itself when the page redirects toredirectUrl. It resolves to that URL, with itscodeortokenin the query string, ready for the app to exchange - or to null if the person closed it first.
As of iOS 11, SFSafariViewController no longer shares cookies with Safari - signIn()'s
ASWebAuthenticationSession does, which is why sign-in uses it and open() does not.
The full OAuth flow, with PKCE
signIn() covers a redirect-and-read-the-URL flow. For the full flow - PKCE, a provider's
discovery document - expo-auth-session's AuthRequest is a plain class that needs no React, and
its promptAsync opens this same session:
import { AuthRequest, makeRedirectUri, exchangeCodeAsync } from 'expo-auth-session';
const discovery = { authorizationEndpoint: '...', tokenEndpoint: '...' };
const request = new AuthRequest({
clientId: 'my-client',
scopes: ['openid', 'profile'],
redirectUri: makeRedirectUri({ scheme: 'myapp' }),
});
const result = await request.promptAsync(discovery);
if (result.type === 'success') {
const tokens = await exchangeCodeAsync(
{
clientId: 'my-client',
code: result.params['code']!,
redirectUri: request.redirectUri,
extraParams: { code_verifier: request.codeVerifier! },
},
discovery,
);
}expo-auth-session is a separate package (npx expo install expo-auth-session); Browser does
not depend on it.
Without the module
open() and signIn() resolve without opening anything - signIn() resolves to null, as though
the person had closed the page immediately.
Reference
Browserservice@ng-native/expoimport { Browser } from '@ng-native/expo';Methods
open(url: string): Promise<void>Open a page in the in-app browser. Resolves when it is closed.
signIn(url: string, redirectUrl: string): Promise<string | null>Open a sign-in page, and resolve to the URL it redirected back to - or null if they closed it first.