npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@authress/login-react-native

v0.1.7

Published

Authress authentication SDK for React Native. Implements the full OAuth 2.0+ flow with native mobile storage and deep link handling for iOS and Android.

Downloads

256

Readme

@authress/login-react-native

Authress authentication SDK for React Native. Implements the full OAuth 2.0 login flow with native mobile storage and deep link handling for iOS and Android.

Installation

npm install @authress/login-react-native react-native-encrypted-storage react-native-nitro-cookies react-native-quick-crypto

Setup

Android

1. Configure the deep link intent filter

In android/app/src/main/AndroidManifest.xml, add an intent filter to your main activity so Android routes the redirect URI back to your app:

<activity
  android:name=".MainActivity"
  android:launchMode="singleTask"
  ...>

  <!-- existing intent filters -->

  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <!-- DEFAULT: required for the activity to receive implicit intents from outside the app -->
    <category android:name="android.intent.category.DEFAULT" />
    <!-- BROWSABLE: required so Chrome and Chrome Custom Tabs can trigger this intent -->
    <category android:name="android.intent.category.BROWSABLE" />
    <!-- Must match the redirectUri you pass to LoginClient -->
    <data android:scheme="com.yourapp" android:host="auth" android:pathPrefix="/callback" />
  </intent-filter>
</activity>

2. Forward the deep link to React Native

In android/app/src/main/java/.../MainActivity.kt, if you aren't already processing intents, you need to accept the callback:

import android.content.Intent
import com.facebook.react.ReactActivity

class MainActivity : ReactActivity() {
  override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
  }
}

iOS

1. Register the URL scheme

In ios/YourApp/Info.plist, add:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <!-- Must match the scheme in the redirectUri you pass to LoginClient -->
      <string>com.yourapp</string>
    </array>
  </dict>
</array>

2. Forward the deep link to React Native

In ios/YourApp/AppDelegate.swift:

import React

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(_ app: UIApplication, open url: URL,
                   options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
    return RCTLinkingManager.application(app, open: url, options: options)
  }
}

Or in AppDelegate.mm (Objective-C):

#import <React/RCTLinkingManager.h>

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  return [RCTLinkingManager application:application openURL:url options:options];
}

3. Install native pods

cd ios && pod install

Setup

Create a single LoginClient instance for your app — typically in a module you import wherever authentication is needed.

import { LoginClient } from '@authress/login-react-native';

export const loginClient = new LoginClient({
  // Your Authress custom domain — https://authress.io/app/#/setup?focus=domain
  authressApiUrl: 'https://login.yourdomain.com',

  // Your application ID — https://authress.io/app/#/manage?focus=applications
  applicationId: 'app_your-app-id',

  // The deep link URI Authress redirects back to after login.
  // Must match a registered redirect URI for the application.
  redirectUri: 'com.yourapp://auth/callback',
});

The constructor throws synchronously if any required setting is missing or invalid. It also automatically registers a deep link listener — when the user returns from the Authress login page, the SDK completes the authentication request without any extra wiring in your app.

Optional logger

Pass any console-compatible logger as the second argument to see debug output:

const loginClient = new LoginClient(settings, console);

Usage

All methods return a Result from the neverthrow library. A Result is either Ok(value) or Err(error) — it never throws. Use .match(), .isOk(), .isErr(), or .unwrapOr() to handle both cases.

Check if the user is logged in

Call this on every route change to keep session state current. It uses a cached token when available; otherwise it calls the Authress server.

const isLoggedIn = await loginClient.userIsLoggedIn();
if (isLoggedIn) {
  // session is valid — proceed to the app
} else {
  // no active session — show the login screen
}

Log in — full authentication flow

Start the login request, open the browser, and the SDK takes care of the rest — it listens for the deep link redirect and completes the authentication automatically.

import { Linking } from 'react-native';

const result = await loginClient.authenticate({
  // Optional: specify a connection directly, or let the user pick on the Authress-hosted login page
  connectionId: 'google',
});

if (result.isOk()) {
  // Open the Authress-hosted login page in the device browser
  await Linking.openURL(result.value.authenticationUrl);
} else {
  console.error('Failed to start login', result.error);
}

When the user returns via the deep link, the SDK automatically calls completeAuthenticationRequest and resolves any pending waitForToken calls.

Get a token for API calls

Use waitForToken when you need a bearer token and are willing to wait for a session to become active (e.g. on app startup while restoring a previous session).

const result = await loginClient.waitForToken({ timeoutInMillis: 5000 });

if (result.isOk()) {
  // Token is available — retrieve it with getToken()
  const tokenResult = await loginClient.getToken();
  if (tokenResult.isOk()) {
    const token = tokenResult.value;
    // Use as: Authorization: Bearer <token>
  }
} else {
  // result.error.code === 'TokenTimeoutError'
  // No token arrived within the timeout — redirect to login
}

Use getToken() directly when you need the token string immediately with no waiting:

const tokenResult = await loginClient.getToken();
if (tokenResult.isOk()) {
  const token = tokenResult.value;
}
// Returns Err(NotLoggedInError) immediately if there is no active session

Get user identity

Returns decoded claims from the session token — useful for personalising the UI.

const result = await loginClient.getUserIdentity();

if (result.isOk()) {
  console.log(result.value.userId); // e.g. 'user|00001'
  // result.value also contains all other JWT claims
} else {
  // result.error.code === 'NotLoggedInError'
}

Get full user profile

Fetches the user's profile from Authress, including all linked identities. Requires an active session.

const result = await loginClient.getUserProfile();

if (result.isOk()) {
  for (const { connection } of result.value.linkedIdentities) {
    console.log(connection.connectionId, connection.userId);
  }
} else if (result.error.code === 'NotLoggedInError') {
  // user is not logged in
} else {
  // HTTP error
}

Log out

Clears the local session and invalidates the server-side session.

await loginClient.logout();
// Result is always Ok — errors during server-side logout are swallowed

After logout, getToken() returns Err, waitForToken() blocks again, and userIsLoggedIn() returns false.

Link an additional identity

Links a new identity provider to the currently logged-in user. Follows the same flow as authenticate — open authenticationUrl in the browser and the SDK handles the redirect automatically. Either connectionId or tenantLookupIdentifier is required.

const result = await loginClient.linkIdentity({ connectionId: 'github' });

if (result.isOk()) {
  await Linking.openURL(result.value.authenticationUrl);
} else if (result.error.code === 'NotLoggedInError') {
  // user must be logged in to link an identity
} else {
  console.error('Link identity failed', result.error);
}

MFA devices

// List registered MFA devices
const devicesResult = await loginClient.getDevices();
const devices = devicesResult.unwrapOr([]);

// Remove a device
const deleteResult = await loginClient.deleteDevice(deviceId);
if (deleteResult.isErr()) {
  console.error('Failed to remove device', deleteResult.error);
}

Error handling

All errors are typed and carry a discriminating property. No method throws — use .isErr() to check for failure, then inspect the error.

Application errors

Returned as Err values when a precondition is not met. Match on error.code:

| Class | error.code | When | |---|---|---| | NotLoggedInError | 'NotLoggedInError' | Operation requires a logged-in session | | NoAuthenticationRequestInProgressError | 'NoAuthenticationRequestInProgressError' | completeAuthenticationRequest called with no pending login | | AuthenticationRequestMismatchError | 'AuthenticationRequestMismatchError' | authenticationRequestId in the redirect does not match the pending request | | TokenTimeoutError | 'TokenTimeoutError' | waitForToken timeout elapsed before a session arrived | | InvalidConnectionError | 'InvalidConnectionError' | linkIdentity called without connectionId or tenantLookupIdentifier | | SecurityContextError | 'SecurityContextError' | Encrypted storage is unavailable (device security context error) |

HTTP errors

Returned when a network request to the Authress service fails. All three types are part of the AuthressHttpError union. Match on error.name:

| error.name | When | |---|---| | 'AuthressHttpNetworkError' | Request never reached the server (network offline, DNS failure). Retried up to 5 times before returning this error. | | 'AuthressHttpClientError' | Authress returned a 4xx response | | 'AuthressHttpServiceError' | Authress returned a 5xx response |

Each HTTP error includes url, method, and data. Client and service errors also include status and headers.

Example: handling all error cases

import type { AuthressHttpError } from '@authress/login-react-native';

const result = await loginClient.authenticate({ connectionId: 'google' });

if (result.isErr()) {
  const error = result.error;

  // Application errors — check error.code
  if (error.code === 'SecurityContextError') {
    // encrypted storage unavailable — device security context error
  }

  // HTTP errors — check error.name
  else if (error.name === 'AuthressHttpNetworkError') {
    // device is offline
  } else if (error.name === 'AuthressHttpClientError') {
    console.error(`Bad request: ${error.status}`, error.data);
  } else if (error.name === 'AuthressHttpServiceError') {
    console.error(`Authress service error: ${error.status}`);
  }
}

API reference

new LoginClient(settings, logger?)

| Parameter | Type | Required | Description | |---|---|---|---| | authressApiUrl | string | Yes | Your Authress custom domain | | applicationId | string | Yes | Your Authress application ID | | redirectUri | string | Yes | Deep link URI registered for the application | | logger | Logger | No | Optional logger (console works) |

Throws synchronously on invalid settings.


userIsLoggedIn()

Promise<boolean>

Checks if a valid session exists. Uses the cached token when available; otherwise calls the Authress API. Returns Ok(true) if the session is active, Ok(false) if not logged in or if the server call fails.

Call on every route change.


authenticate(options?)

Promise<Result<AuthenticateResponse, AuthressHttpError | SecurityContextError>>

Starts the login flow. Returns authenticationUrl to open in the device browser. The SDK automatically handles the deep link redirect to complete the flow.

| Option | Type | Description | |---|---|---| | connectionId | string | Log in directly with a specific provider connection | | tenantLookupIdentifier | string | Resolve the connection from a tenant identifier | | inviteId | string | Accept an invitation | | redirectUrl | string | Override the redirect URI from settings | | scopes | string[] | Additional scopes to request | | audiences | string[] | Additional audiences for the token | | connectionProperties | Record<string, string> | Provider-specific properties | | multiAccount | boolean | Enable multi-account login (default: false) |


completeAuthenticationRequest(params)

Promise<Result<void, AuthFlowError | AuthressHttpError>>

Completes the login flow after the deep link redirect. Called automatically by the SDK when the deep link is received — you only need to call this directly if you are managing the deep link yourself.


getToken()

Promise<Result<string, NotLoggedInError>>

Returns the current bearer token, or Err(NotLoggedInError) if there is no active session. Does not wait or make network calls.


waitForToken(options?)

Promise<Result<void, TokenTimeoutError>>

Blocks until a session token is available or the timeout elapses. Use getToken() after this resolves to retrieve the token string.

| Option | Type | Default | Description | |---|---|---|---| | timeoutInMillis | number | 5000 | Timeout in ms. 0 = fail immediately. -1 = wait indefinitely. |


logout()

Promise<Result<void, never>>

Clears the local session and calls the Authress logout endpoint. Always resolves Ok — server-side errors are swallowed.


getUserIdentity()

Promise<Result<UserIdentity, NotLoggedInError>>

Returns decoded claims from the session token. identity.userId is the user's unique identifier. The identity object also contains all other JWT claims.


getUserProfile()

Promise<Result<UserProfile, AuthressHttpError | NotLoggedInError>>

Fetches the user's full profile from Authress, including all linked identities (profile.linkedIdentities).


linkIdentity(options)

Promise<Result<AuthenticateResponse, AuthressHttpError | SecurityContextError | NotLoggedInError | InvalidConnectionError>>

Links a new identity provider to the current user. Returns authenticationUrl to open in the device browser. Either connectionId or tenantLookupIdentifier is required.


getDevices()

Promise<Result<Device[], AuthressHttpError | NotLoggedInError>>

Returns the list of MFA devices registered for the current user. Returns Ok([]) if not logged in or no devices are registered.


deleteDevice(deviceId)

Promise<Result<void, AuthressHttpError | NotLoggedInError>>

Removes the MFA device with the given deviceId.