react-native-app-auth: OAuth2 in a mobile app without a WebView
React native bridge for AppAuth - an SDK for communicating with OAuth2 providers
At a glance
- What is it?
- A React Native bridge over the AppAuth SDKs for iOS and Android, supporting the authorization code flow with PKCE and refusing WebViews for the reasons RFC 8252 gives.
- Who is it for?
- react-native-app-auth earns its place by not being a JavaScript OAuth implementation at all. It delegates to AppAuth on both platforms, which means the login screen is the real system browser on iOS and Custom Tabs on Android, the redirect comes back through the native app, and PKCE is handled by code that has been audited for it rather than by a library you assembled.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the bridge actually wraps
The description is one line: a React Native bridge for AppAuth, an SDK for communicating with OAuth2 providers. Underneath are two native libraries maintained separately, AppAuth-iOS and AppAuth-Android, and the JavaScript package here is the layer that lets a React Native app call them.
That architecture is the whole argument for using it. AppAuth is not a port; it is the same client both native SDKs ship. The README says it should support any OAuth provider that implements the OAuth2 specification, and it names the two specs that matter: OAuth 2.0 per RFC 6749 and OpenID Connect.
One constraint is stated without hedging. Only the Authorization Code Flow is supported. There is no implicit grant, no resource owner password credentials, and no device flow in the library. For a mobile app that is the correct choice, because the other flows are either deprecated or inappropriate for a public client, but it does mean the library will not help if your provider only offers something else.
Why WebViews are explicitly out of scope
The README has a section explaining why you would want the library, and the strongest sentence in it is a refusal. AppAuth follows the best practices in RFC 8252, OAuth 2.0 for native apps, which includes using `ASWebAuthenticationSession` and `SFSafariViewController` on iOS and Custom Tabs on Android. WebViews are explicitly not supported, and the README attributes that to the security and usability reasons explained in Section 8.12 of the RFC.
The practical difference is visible to a user. With the system browser or a Custom Tab, the login page runs in a context the app cannot inspect, cookies live with the browser rather than inside your app sandbox, and autofill and password managers work. With a WebView you rebuild all of that badly, and you create a place where a phishing page looks exactly like the real thing because your app painted it.
The second half of the security story is PKCE. The README notes that AppAuth supports the PKCE extension, which it calls Pixy, created to secure authorization codes in public clients when custom URI scheme redirects are used. Since a mobile app has no secret to hide, PKCE is what makes the authorization code flow safe there.
Two provider lists, and the difference between them
The README keeps OpenID providers and OAuth2 providers in separate lists, and the reason matters more than the length of either one. The OpenID list is described as OpenID compliant, which means you can use autodiscovery, so the library can fetch the authorization, token and userinfo endpoints from the issuer's configuration document instead of you pasting URLs. That list covers IdentityServer4 and IdentityServer3, FusionAuth, Google, Okta, Keycloak, Azure Active Directory, AWS Cognito, Asgardeo and Microsoft, each with a link to an example configuration on the documentation site.
The OAuth2 list is described as implementing the OAuth2 spec but not being OpenID providers, which means you must configure the authorization and token endpoints yourself. That list covers Uber, Fitbit, Dropbox, Reddit, Coinbase, GitHub, Slack, Strava, Spotify, Unsplash and Imgur.
The documentation links are the real content of both lists. A provider name tells you nothing about which scopes that provider accepts or whether it requires PKCE, and each example configuration on commerce.nearform.com is where that lives. Start from the list, follow the one example closest to your provider, and treat the differences as the work rather than the library.
Running the demo apps, and a path discrepancy worth noting
The contributing section explains how to run the iOS and Android example apps after cloning. The Android path is three commands:
cd react-native-app-auth/Example
yarn
npx react-native run-androidThe iOS path adds a CocoaPods step inside the ios directory before the run command, with a note further down that you need the simulator or emulator open first.
The commands are worth reading against the current tree, because they are not quite aligned. The repository tree has an `examples/` directory at the top level rather than an `Example/` directory, and the examples listed in the repository metadata are `examples/demo/` and `examples/expo-cng/`. The root `package.json` lists its workspaces as `packages/*` and `examples/demo`, and its scripts point at those workspaces, with `start:demo:ios` and `start:demo:android` delegating to a workspace called `rnaa-demo`. So the README's example path describes an older layout than the one in the tree, and the workspace scripts are the more current entry point.
That is a small documentation drift rather than a real problem, but it is the kind of thing that costs an afternoon if you trust the README first.
Releases that track Expo and the Android platform
The release history shows a library that responds to the platforms it sits on. Version 8.3.0, published on 2026-05-20, added support for Expo 55 AppDelegate declarations without the public class modifier, exposed underlying native authorization errors on `error.nativeError` for debugging while keeping `error.message` user-safe, removed duplicate iOS auth `state` and `nonce` parameters, and added a missing RCTLinkingManager fallback for non-auth URLs in the AppDelegate setup documentation.
Version 8.4.0, on 2026-05-28, added `androidPrefersEphemeralSession` to request an ephemeral Custom Tab on Android where supported, and updated AndroidX Browser to 1.9.0. That update has a cost the release notes spell out: Android projects now need minimum SDK 21 or higher, compile SDK 36 or higher, and Android Gradle Plugin 8.9.1 or higher.
Version 8.4.1, published on 2026-07-06, fixed Expo config plugin support for Swift AppDelegate templates that omit `public` before the class declaration, and fixed URL scheme extraction from AppAuth redirect URLs that use a single slash. Both recent releases are about Expo configuration, which tells you where most of the friction now is: not the OAuth flow, but wiring redirect URIs into a project that generates its native files.
What the repository shows about maintenance
The tree is small and says a lot about scope. `packages/` holds the library, `examples/` the demos, `docs/` the documentation, and `.changeset/` the versioning workflow. There is an `app.json`, an `.eslintrc` with `.eslintignore` and `.prettierrc`, and a `yarn.lock` at the root.
The root `package.json` is where the interesting choices live. It is marked private and versioned 1.0.0 as `rnaa`, the monorepo rather than the published package. Versioning is done with changesets, with `@changesets/cli` and a compact changelog generator as dev dependencies, and the `changeset` script runs it. The Node requirement is stated as 18.0.0 or higher.
The dependency versions on the linting side are a fossil record: eslint 6.8.0, prettier 1.19.1, babel-eslint 10.0.3, and a set of eslint plugins pinned at the versions current to that era. The `workspaces` block also declares a `nohoist` list that pushes `react-native`, `@react-native` and `react-native-app-auth` out of the hoisted tree, which is the standard Yarn workaround for React Native monorepos.
The README states a maintenance status badge and notes that the current version supports react-native 0.63 and later, with v5.1.3 as the last version compatible with anything older. The repository is not archived, was pushed to on 2026-09-28, and has 2,253 stars, 473 forks and 164 open issues under the MIT license.
Editorial conclusion
react-native-app-auth earns its place by not being a JavaScript OAuth implementation at all. It delegates to AppAuth on both platforms, which means the login screen is the real system browser on iOS and Custom Tabs on Android, the redirect comes back through the native app, and PKCE is handled by code that has been audited for it rather than by a library you assembled. The trade is that configuration lives in native project files, so a cross platform team needs someone who can read an Xcode plist and a manifest. Set up one OpenID provider with autodiscovery first, confirm the redirect lands back in your app on a device, and only then work through the OAuth2-only providers that need manual endpoints.
Frequently asked questions
What does react-native-app-auth do?
It is a React Native bridge over the AppAuth-iOS and AppAuth-Android SDKs, letting a mobile app talk to OAuth 2.0 and OpenID Connect providers. Only the Authorization Code Flow is supported, and PKCE is handled by AppAuth itself.
Which OAuth providers does react-native-app-auth support?
The README lists OpenID compliant providers where autodiscovery works, including Google, Okta, Keycloak, Azure Active Directory, AWS Cognito, FusionAuth, Asgardeo and IdentityServer, plus OAuth2-only providers such as GitHub, Slack, Spotify, Strava, Dropbox, Uber, Coinbase, Reddit, Fitbit, Unsplash and Imgur, where you configure the endpoints yourself.
Why does react-native-app-auth not use a WebView for login?
AppAuth follows RFC 8252 for OAuth 2.0 in native apps, using `ASWebAuthenticationSession` and `SFSafariViewController` on iOS and Custom Tabs on Android. The README says WebViews are explicitly not supported, citing the security and usability reasons in Section 8.12 of that RFC, since a WebView cannot keep cookies out of the app sandbox and looks identical to a phishing page.
Does react-native-app-auth work with Expo?
There is an Expo config plugin and an `examples/expo-cng/` example. Recent releases added support for Expo 55 AppDelegate declarations without the public class modifier and fixed config plugin handling for Swift AppDelegate templates, so Expo support is actively maintained but the redirect URI wiring still needs care.
How do I run the react-native-app-auth example app?
The README documents three commands for Android and the same with a `pod install` step for iOS, starting from a directory called `Example`. The current tree instead has `examples/` with a `demo` workspace, and the root package.json scripts `start:demo:ios` and `start:demo:android` are the newer entry point. You need the emulator or simulator running before either.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/formidablelabs-react-native-app-auth)