react-native-nitro-auth 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +602 -57
- package/android/build.gradle +8 -2
- package/android/gradle.properties +2 -2
- package/android/src/main/cpp/JniOnLoad.cpp +1 -0
- package/android/src/main/cpp/PlatformAuth+Android.cpp +37 -4
- package/android/src/main/java/com/auth/AuthAdapter.kt +586 -69
- package/android/src/main/java/com/auth/GoogleSignInActivity.kt +17 -4
- package/android/src/main/java/com/auth/MicrosoftAuthActivity.kt +25 -0
- package/app.plugin.js +115 -5
- package/cpp/AuthCache.cpp +72 -19
- package/cpp/HybridAuth.cpp +20 -0
- package/cpp/HybridAuth.hpp +1 -0
- package/ios/AuthAdapter.swift +470 -53
- package/ios/KeychainStore.swift +43 -0
- package/ios/PlatformAuth+iOS.mm +34 -3
- package/lib/commonjs/Auth.web.js +262 -10
- package/lib/commonjs/Auth.web.js.map +1 -1
- package/lib/commonjs/index.js +7 -11
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/service.js +130 -1
- package/lib/commonjs/service.js.map +1 -1
- package/lib/commonjs/service.web.js +32 -6
- package/lib/commonjs/service.web.js.map +1 -1
- package/lib/commonjs/ui/social-button.js +46 -8
- package/lib/commonjs/ui/social-button.js.map +1 -1
- package/lib/commonjs/ui/social-button.web.js +46 -8
- package/lib/commonjs/ui/social-button.web.js.map +1 -1
- package/lib/commonjs/use-auth.js +27 -2
- package/lib/commonjs/use-auth.js.map +1 -1
- package/lib/commonjs/utils/logger.js +1 -1
- package/lib/commonjs/utils/logger.js.map +1 -1
- package/lib/module/Auth.web.js +262 -10
- package/lib/module/Auth.web.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/service.js +130 -1
- package/lib/module/service.js.map +1 -1
- package/lib/module/service.web.js +32 -1
- package/lib/module/service.web.js.map +1 -1
- package/lib/module/ui/social-button.js +47 -9
- package/lib/module/ui/social-button.js.map +1 -1
- package/lib/module/ui/social-button.web.js +47 -9
- package/lib/module/ui/social-button.web.js.map +1 -1
- package/lib/module/use-auth.js +27 -2
- package/lib/module/use-auth.js.map +1 -1
- package/lib/module/utils/logger.js +1 -1
- package/lib/module/utils/logger.js.map +1 -1
- package/lib/typescript/commonjs/Auth.nitro.d.ts +10 -2
- package/lib/typescript/commonjs/Auth.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/Auth.web.d.ts +9 -1
- package/lib/typescript/commonjs/Auth.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/AuthStorage.nitro.d.ts +7 -0
- package/lib/typescript/commonjs/AuthStorage.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/service.d.ts +8 -1
- package/lib/typescript/commonjs/service.d.ts.map +1 -1
- package/lib/typescript/commonjs/service.web.d.ts +25 -1
- package/lib/typescript/commonjs/service.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/social-button.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/social-button.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/use-auth.d.ts +13 -8
- package/lib/typescript/commonjs/use-auth.d.ts.map +1 -1
- package/lib/typescript/commonjs/utils/logger.d.ts +5 -5
- package/lib/typescript/commonjs/utils/logger.d.ts.map +1 -1
- package/lib/typescript/module/Auth.nitro.d.ts +10 -2
- package/lib/typescript/module/Auth.nitro.d.ts.map +1 -1
- package/lib/typescript/module/Auth.web.d.ts +9 -1
- package/lib/typescript/module/Auth.web.d.ts.map +1 -1
- package/lib/typescript/module/AuthStorage.nitro.d.ts +7 -0
- package/lib/typescript/module/AuthStorage.nitro.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/service.d.ts +8 -1
- package/lib/typescript/module/service.d.ts.map +1 -1
- package/lib/typescript/module/service.web.d.ts +25 -1
- package/lib/typescript/module/service.web.d.ts.map +1 -1
- package/lib/typescript/module/ui/social-button.d.ts.map +1 -1
- package/lib/typescript/module/ui/social-button.web.d.ts.map +1 -1
- package/lib/typescript/module/use-auth.d.ts +13 -8
- package/lib/typescript/module/use-auth.d.ts.map +1 -1
- package/lib/typescript/module/utils/logger.d.ts +5 -5
- package/lib/typescript/module/utils/logger.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/AuthProvider.hpp +4 -0
- package/nitrogen/generated/shared/c++/HybridAuthSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridAuthSpec.hpp +1 -0
- package/nitrogen/generated/shared/c++/LoginOptions.hpp +17 -3
- package/nitrogen/generated/shared/c++/MicrosoftPrompt.hpp +84 -0
- package/package.json +13 -10
- package/react-native-nitro-auth.podspec +4 -2
- package/src/Auth.nitro.ts +17 -2
- package/src/Auth.web.ts +388 -22
- package/src/AuthStorage.nitro.ts +11 -2
- package/src/index.ts +2 -2
- package/src/service.ts +168 -2
- package/src/service.web.ts +41 -1
- package/src/ui/social-button.tsx +34 -4
- package/src/ui/social-button.web.tsx +34 -4
- package/src/use-auth.ts +37 -3
- package/src/utils/logger.ts +5 -5
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
🚀 **High-performance, JSI-powered Authentication for React Native.**
|
|
8
8
|
|
|
9
|
-
Nitro Auth is a modern authentication library for React Native built on top of [Nitro Modules](https://github.com/mrousavy/nitro). It provides a unified, type-safe API for Google and
|
|
9
|
+
Nitro Auth is a modern authentication library for React Native built on top of [Nitro Modules](https://github.com/mrousavy/nitro). It provides a unified, type-safe API for Google, Apple, and Microsoft Sign-In with zero-bridge overhead.
|
|
10
10
|
|
|
11
11
|
## Why Nitro Auth?
|
|
12
12
|
|
|
@@ -29,19 +29,75 @@ Nitro Auth is designed to replace legacy modules like `@react-native-google-sign
|
|
|
29
29
|
- **Auto-Refresh**: Synchronous access to tokens with automatic silent refresh.
|
|
30
30
|
- **Google One-Tap / Sheet**: Modern login experience on Android (Credential Manager) and iOS (Sign-In Sheet).
|
|
31
31
|
- **Error Metadata**: Detailed native error messages for easier debugging.
|
|
32
|
-
- **Custom Storage**: Pluggable storage adapters for secure persistence (e.g
|
|
32
|
+
- **Custom Storage**: Pluggable storage adapters for secure persistence (e.g. Keychain, MMKV, AsyncStorage).
|
|
33
33
|
- **Refresh Interceptors**: Listen to token updates globally.
|
|
34
34
|
|
|
35
35
|
## Installation
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
bun add react-native-nitro-auth react-native-nitro-modules
|
|
39
|
-
|
|
39
|
+
# or
|
|
40
|
+
npm install react-native-nitro-auth react-native-nitro-modules
|
|
41
|
+
# or
|
|
42
|
+
yarn add react-native-nitro-auth react-native-nitro-modules
|
|
43
|
+
# or
|
|
44
|
+
pnpm add react-native-nitro-auth react-native-nitro-modules
|
|
40
45
|
```
|
|
41
46
|
|
|
47
|
+
For Expo projects, rebuild native code after installation:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
bunx expo prebuild
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Testing locally (example app + Microsoft login)
|
|
54
|
+
|
|
55
|
+
Fastest way to confirm the package and Microsoft login work:
|
|
56
|
+
|
|
57
|
+
1. **Azure app (one-time)**
|
|
58
|
+
In [Azure Portal](https://portal.azure.com) → **Azure Active Directory** → **App registrations** → **New registration**:
|
|
59
|
+
- Name: e.g. `Nitro Auth Example`
|
|
60
|
+
- Supported account types: **Accounts in any organizational directory and personal Microsoft accounts**
|
|
61
|
+
- Redirect URI (add after creation):
|
|
62
|
+
- **Android**: `msauth://com.auth.example/<client-id>`
|
|
63
|
+
- **iOS**: `msauth.com.auth.example://auth` (use your bundle id)
|
|
64
|
+
- Under **Authentication** → **Platform configurations** → add **Mobile and desktop applications** with the Android redirect URI above and the iOS one if testing on iOS.
|
|
65
|
+
Copy the **Application (client) ID**.
|
|
66
|
+
|
|
67
|
+
2. **Env file**
|
|
68
|
+
From the repo root:
|
|
69
|
+
```bash
|
|
70
|
+
cd apps/example
|
|
71
|
+
cp .env.example .env.local
|
|
72
|
+
```
|
|
73
|
+
Edit `.env.local` and set at least:
|
|
74
|
+
```bash
|
|
75
|
+
MICROSOFT_CLIENT_ID=<your-application-client-id>
|
|
76
|
+
MICROSOFT_TENANT=common
|
|
77
|
+
```
|
|
78
|
+
(Google/Apple can stay placeholder if you only care about Microsoft.)
|
|
79
|
+
|
|
80
|
+
3. **Run the app**
|
|
81
|
+
From the **monorepo root**:
|
|
82
|
+
```bash
|
|
83
|
+
bun install
|
|
84
|
+
bun run start
|
|
85
|
+
```
|
|
86
|
+
In a second terminal:
|
|
87
|
+
```bash
|
|
88
|
+
bun run example:android
|
|
89
|
+
# or
|
|
90
|
+
bun run example:ios
|
|
91
|
+
```
|
|
92
|
+
Wait for the app to install and open.
|
|
93
|
+
|
|
94
|
+
4. **Test Microsoft**
|
|
95
|
+
In the app, tap **Sign in with Microsoft**. A browser or in-app tab opens; sign in with a Microsoft/personal account, then you should return to the app with the user shown (email, name, provider MICROSOFT).
|
|
96
|
+
If you see "configuration_error", check `MICROSOFT_CLIENT_ID` and that the redirect URI in Azure matches your app (e.g. `msauth://com.auth.example/<client-id>` for the example app).
|
|
97
|
+
|
|
42
98
|
### Expo Setup
|
|
43
99
|
|
|
44
|
-
Add the plugin to `app.json`:
|
|
100
|
+
Add the plugin to `app.json` or `app.config.js`:
|
|
45
101
|
|
|
46
102
|
```json
|
|
47
103
|
{
|
|
@@ -54,26 +110,197 @@ Add the plugin to `app.json`:
|
|
|
54
110
|
"googleClientId": "YOUR_IOS_CLIENT_ID.apps.googleusercontent.com",
|
|
55
111
|
"googleServerClientId": "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com",
|
|
56
112
|
"googleUrlScheme": "com.googleusercontent.apps.YOUR_IOS_CLIENT_ID",
|
|
57
|
-
"appleSignIn": true
|
|
113
|
+
"appleSignIn": true,
|
|
114
|
+
"microsoftClientId": "YOUR_AZURE_AD_CLIENT_ID",
|
|
115
|
+
"microsoftTenant": "common",
|
|
116
|
+
"microsoftB2cDomain": "your-tenant.b2clogin.com"
|
|
58
117
|
},
|
|
59
118
|
"android": {
|
|
60
|
-
"googleClientId": "
|
|
119
|
+
"googleClientId": "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com",
|
|
120
|
+
"microsoftClientId": "YOUR_AZURE_AD_CLIENT_ID",
|
|
121
|
+
"microsoftTenant": "common",
|
|
122
|
+
"microsoftB2cDomain": "your-tenant.b2clogin.com"
|
|
61
123
|
}
|
|
62
124
|
}
|
|
63
125
|
]
|
|
64
|
-
]
|
|
126
|
+
],
|
|
127
|
+
"extra": {
|
|
128
|
+
"googleWebClientId": "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com",
|
|
129
|
+
"microsoftClientId": "YOUR_AZURE_AD_CLIENT_ID",
|
|
130
|
+
"microsoftTenant": "common",
|
|
131
|
+
"microsoftB2cDomain": "your-tenant.b2clogin.com",
|
|
132
|
+
"appleWebClientId": "com.example.web"
|
|
133
|
+
}
|
|
65
134
|
}
|
|
66
135
|
}
|
|
67
136
|
```
|
|
68
137
|
|
|
69
|
-
|
|
70
|
-
|
|
138
|
+
**Using environment variables (recommended):**
|
|
139
|
+
|
|
140
|
+
Create a `.env.local` file:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# iOS Client ID
|
|
144
|
+
GOOGLE_IOS_CLIENT_ID=your-ios-client-id.apps.googleusercontent.com
|
|
145
|
+
GOOGLE_IOS_URL_SCHEME=com.googleusercontent.apps.your-ios-client-id
|
|
146
|
+
GOOGLE_SERVER_CLIENT_ID=your-web-client-id.apps.googleusercontent.com
|
|
147
|
+
|
|
148
|
+
# Web Client ID (used for Android OAuth flow)
|
|
149
|
+
GOOGLE_WEB_CLIENT_ID=your-web-client-id.apps.googleusercontent.com
|
|
150
|
+
|
|
151
|
+
# Microsoft/Azure AD (optional)
|
|
152
|
+
MICROSOFT_CLIENT_ID=your-azure-ad-application-id
|
|
153
|
+
MICROSOFT_TENANT=common
|
|
154
|
+
MICROSOFT_B2C_DOMAIN=your-tenant.b2clogin.com
|
|
155
|
+
|
|
156
|
+
# Apple (web only)
|
|
157
|
+
APPLE_WEB_CLIENT_ID=com.example.web
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Then reference them in `app.config.js`:
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
import "dotenv/config";
|
|
164
|
+
|
|
165
|
+
export default {
|
|
166
|
+
expo: {
|
|
167
|
+
plugins: [
|
|
168
|
+
[
|
|
169
|
+
"react-native-nitro-auth",
|
|
170
|
+
{
|
|
171
|
+
ios: {
|
|
172
|
+
googleClientId: process.env.GOOGLE_IOS_CLIENT_ID,
|
|
173
|
+
googleServerClientId: process.env.GOOGLE_SERVER_CLIENT_ID,
|
|
174
|
+
googleUrlScheme: process.env.GOOGLE_IOS_URL_SCHEME,
|
|
175
|
+
appleSignIn: true,
|
|
176
|
+
microsoftClientId: process.env.MICROSOFT_CLIENT_ID,
|
|
177
|
+
microsoftTenant: process.env.MICROSOFT_TENANT,
|
|
178
|
+
microsoftB2cDomain: process.env.MICROSOFT_B2C_DOMAIN,
|
|
179
|
+
},
|
|
180
|
+
android: {
|
|
181
|
+
googleClientId: process.env.GOOGLE_WEB_CLIENT_ID,
|
|
182
|
+
microsoftClientId: process.env.MICROSOFT_CLIENT_ID,
|
|
183
|
+
microsoftTenant: process.env.MICROSOFT_TENANT,
|
|
184
|
+
microsoftB2cDomain: process.env.MICROSOFT_B2C_DOMAIN,
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
],
|
|
189
|
+
extra: {
|
|
190
|
+
googleWebClientId: process.env.GOOGLE_WEB_CLIENT_ID,
|
|
191
|
+
microsoftClientId: process.env.MICROSOFT_CLIENT_ID,
|
|
192
|
+
microsoftTenant: process.env.MICROSOFT_TENANT,
|
|
193
|
+
microsoftB2cDomain: process.env.MICROSOFT_B2C_DOMAIN,
|
|
194
|
+
appleWebClientId: process.env.APPLE_WEB_CLIENT_ID,
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
> [!NOTE]
|
|
201
|
+
>
|
|
202
|
+
> - `appleSignIn` on iOS is `false` by default to avoid unnecessary entitlements. Set it to `true` to enable Apple Sign-In.
|
|
203
|
+
> - For Android, use your **Web Client ID** (not Android Client ID) for proper OAuth flow.
|
|
204
|
+
> - If you need `serverAuthCode`, set `googleServerClientId` to your Web Client ID.
|
|
205
|
+
> - Add `googleWebClientId` to `expo.extra` for web platform support.
|
|
206
|
+
> - The `serverAuthCode` is automatically included in `AuthUser` when available (requires backend integration setup in Google Cloud Console).
|
|
207
|
+
> - For Microsoft Sign-In, use `common` tenant for multi-tenant apps, or specify your Azure AD tenant ID for single-tenant apps.
|
|
208
|
+
> - For Azure AD B2C, set `microsoftB2cDomain` and pass the B2C tenant in `microsoftTenant`.
|
|
209
|
+
|
|
210
|
+
### Google OAuth Setup
|
|
211
|
+
|
|
212
|
+
1. Create OAuth client IDs in Google Cloud Console:
|
|
213
|
+
- **iOS client ID** (used by iOS)
|
|
214
|
+
- **Web client ID** (used by Android and for `serverAuthCode`)
|
|
215
|
+
2. Configure your app:
|
|
216
|
+
- Expo: set `googleClientId`, `googleServerClientId`, and `googleUrlScheme`
|
|
217
|
+
- Bare iOS: add `GIDClientID`, `GIDServerClientID`, and URL scheme in `Info.plist`
|
|
218
|
+
- Bare Android: set `nitro_auth_google_client_id` to your **Web client ID**
|
|
219
|
+
3. If you use `serverAuthCode`, make sure OAuth consent screen is configured in Google Cloud.
|
|
220
|
+
|
|
221
|
+
### Apple Sign-In Setup
|
|
222
|
+
|
|
223
|
+
1. **iOS**: enable the “Sign in with Apple” capability in Xcode and in your Apple Developer account.
|
|
224
|
+
2. **Web**: create a Service ID and configure the domain + return URL in Apple Developer.
|
|
225
|
+
3. Configure your app:
|
|
226
|
+
- Expo: set `appleSignIn: true` for iOS.
|
|
227
|
+
- Web: set `appleWebClientId` in `expo.extra` (or `.env`).
|
|
228
|
+
|
|
229
|
+
### Microsoft Azure AD Setup
|
|
230
|
+
|
|
231
|
+
To enable Microsoft Sign-In, you need to register an application in the Azure Portal:
|
|
232
|
+
|
|
233
|
+
1. Go to [Azure Portal](https://portal.azure.com) > Azure Active Directory > App registrations
|
|
234
|
+
2. Click "New registration"
|
|
235
|
+
3. Set the redirect URIs:
|
|
236
|
+
- **iOS**: `msauth.{bundle-identifier}://auth` (e.g., `msauth.com.myapp://auth`)
|
|
237
|
+
- **Android**: `msauth://{package-name}/{client-id}` (e.g., `msauth://com.myapp/00000000-0000-0000-0000-000000000000`)
|
|
238
|
+
- **Web**: `https://your-domain.com` (the page that loads the app)
|
|
239
|
+
4. Under "API permissions", add `openid`, `email`, `profile`, and `User.Read` (Microsoft Graph)
|
|
240
|
+
5. Copy the Application (client) ID for use in your config
|
|
241
|
+
|
|
242
|
+
**Tenant Options:**
|
|
243
|
+
|
|
244
|
+
- `common` - Any Azure AD or personal Microsoft account
|
|
245
|
+
- `organizations` - Any Azure AD account (work/school)
|
|
246
|
+
- `consumers` - Personal Microsoft accounts only
|
|
247
|
+
- `{tenant-id}` - Specific Azure AD tenant
|
|
248
|
+
- **B2C**: set `microsoftB2cDomain` (e.g. `your-tenant.b2clogin.com`) and use a tenant value like `your-tenant.onmicrosoft.com/B2C_1_signin` (or pass a full `https://.../` authority URL).
|
|
71
249
|
|
|
72
250
|
### Bare React Native
|
|
73
251
|
|
|
74
|
-
**iOS
|
|
252
|
+
**iOS**
|
|
253
|
+
|
|
254
|
+
- Add to `Info.plist`: `GIDClientID`, `GIDServerClientID` (optional), `MSALClientID`, `MSALTenant` (optional), `MSALB2cDomain` (optional).
|
|
255
|
+
- Add URL schemes in `Info.plist`:
|
|
256
|
+
- Google: `com.googleusercontent.apps.<YOUR_IOS_CLIENT_ID>`
|
|
257
|
+
- Microsoft: `msauth.<your.bundle.id>` (used for `msauth.<bundle.id>://auth`)
|
|
258
|
+
- Enable the “Sign in with Apple” capability if you use Apple Sign-In.
|
|
259
|
+
|
|
260
|
+
**Android**
|
|
261
|
+
|
|
262
|
+
- Add string resources in `res/values/strings.xml`:
|
|
263
|
+
- `nitro_auth_google_client_id` (Web client ID)
|
|
264
|
+
- `nitro_auth_microsoft_client_id`
|
|
265
|
+
- `nitro_auth_microsoft_tenant` (optional)
|
|
266
|
+
- `nitro_auth_microsoft_b2c_domain` (optional)
|
|
267
|
+
- Add the Microsoft redirect activity to `AndroidManifest.xml`:
|
|
268
|
+
|
|
269
|
+
```xml
|
|
270
|
+
<activity
|
|
271
|
+
android:name="com.auth.MicrosoftAuthActivity"
|
|
272
|
+
android:exported="true">
|
|
273
|
+
<intent-filter>
|
|
274
|
+
<action android:name="android.intent.action.VIEW" />
|
|
275
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
276
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
277
|
+
<data
|
|
278
|
+
android:scheme="msauth"
|
|
279
|
+
android:host="${applicationId}"
|
|
280
|
+
android:path="/YOUR_MICROSOFT_CLIENT_ID" />
|
|
281
|
+
</intent-filter>
|
|
282
|
+
</activity>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Web Setup
|
|
286
|
+
|
|
287
|
+
Nitro Auth reads web configuration from `expo.extra`:
|
|
288
|
+
|
|
289
|
+
```json
|
|
290
|
+
{
|
|
291
|
+
"expo": {
|
|
292
|
+
"extra": {
|
|
293
|
+
"googleWebClientId": "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com",
|
|
294
|
+
"microsoftClientId": "YOUR_AZURE_AD_CLIENT_ID",
|
|
295
|
+
"microsoftTenant": "common",
|
|
296
|
+
"microsoftB2cDomain": "your-tenant.b2clogin.com",
|
|
297
|
+
"appleWebClientId": "com.example.web"
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
75
302
|
|
|
76
|
-
|
|
303
|
+
For Apple web sign-in, `appleWebClientId` must be your Apple Service ID. For Microsoft web, make sure your Azure app includes a Web redirect URI matching your site.
|
|
77
304
|
|
|
78
305
|
## Quick Start
|
|
79
306
|
|
|
@@ -105,13 +332,132 @@ function LoginScreen() {
|
|
|
105
332
|
onPress={() => login("google")}
|
|
106
333
|
disabled={loading || !hasPlayServices}
|
|
107
334
|
/>
|
|
335
|
+
<SocialButton
|
|
336
|
+
provider="apple"
|
|
337
|
+
onPress={() => login("apple")}
|
|
338
|
+
disabled={loading}
|
|
339
|
+
/>
|
|
340
|
+
<SocialButton
|
|
341
|
+
provider="microsoft"
|
|
342
|
+
onPress={() => login("microsoft")}
|
|
343
|
+
disabled={loading}
|
|
344
|
+
/>
|
|
108
345
|
</View>
|
|
109
346
|
);
|
|
110
347
|
}
|
|
111
348
|
```
|
|
112
349
|
|
|
350
|
+
### Microsoft Login Options
|
|
351
|
+
|
|
352
|
+
```tsx
|
|
353
|
+
// Login with specific tenant
|
|
354
|
+
await login("microsoft", {
|
|
355
|
+
tenant: "your-tenant-id",
|
|
356
|
+
prompt: "select_account", // 'login' | 'consent' | 'select_account' | 'none'
|
|
357
|
+
scopes: ["openid", "email", "profile", "User.Read"],
|
|
358
|
+
loginHint: "user@example.com",
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
**B2C example:**
|
|
363
|
+
|
|
364
|
+
```tsx
|
|
365
|
+
await login("microsoft", {
|
|
366
|
+
tenant: "your-tenant.onmicrosoft.com/B2C_1_signin",
|
|
367
|
+
scopes: ["openid", "email", "profile", "offline_access"],
|
|
368
|
+
});
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Migration from @react-native-google-signin/google-signin
|
|
372
|
+
|
|
373
|
+
If you are using `@react-native-google-signin/google-signin`, the migration to Nitro Auth is mostly a drop-in at the API level, but the setup is different because Nitro Auth uses a config plugin and JSI.
|
|
374
|
+
|
|
375
|
+
### 1) Replace the dependency
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
bun remove @react-native-google-signin/google-signin
|
|
379
|
+
bun add react-native-nitro-auth react-native-nitro-modules
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 2) Move configuration to the Nitro Auth plugin
|
|
383
|
+
|
|
384
|
+
Nitro Auth does not use `GoogleSignin.configure(...)`. Instead, set your client IDs via the config plugin (Expo) or native config (bare).
|
|
385
|
+
|
|
386
|
+
**Expo** (recommended):
|
|
387
|
+
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"expo": {
|
|
391
|
+
"plugins": [
|
|
392
|
+
[
|
|
393
|
+
"react-native-nitro-auth",
|
|
394
|
+
{
|
|
395
|
+
"ios": {
|
|
396
|
+
"googleClientId": "YOUR_IOS_CLIENT_ID.apps.googleusercontent.com",
|
|
397
|
+
"googleUrlScheme": "com.googleusercontent.apps.YOUR_IOS_CLIENT_ID"
|
|
398
|
+
},
|
|
399
|
+
"android": {
|
|
400
|
+
"googleClientId": "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com"
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
]
|
|
404
|
+
],
|
|
405
|
+
"extra": {
|
|
406
|
+
"googleWebClientId": "YOUR_WEB_CLIENT_ID.apps.googleusercontent.com"
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**Bare React Native:**
|
|
413
|
+
|
|
414
|
+
- iOS: add `GIDClientID` (and optionally `GIDServerClientID`) to `Info.plist` and set the URL scheme.
|
|
415
|
+
- Android: add `nitro_auth_google_client_id` string resource in `res/values/strings.xml` (use your Web Client ID).
|
|
416
|
+
|
|
417
|
+
### 3) Update API usage
|
|
418
|
+
|
|
419
|
+
| @react-native-google-signin/google-signin | Nitro Auth |
|
|
420
|
+
| ----------------------------------------- | --------------------------------------------------------- |
|
|
421
|
+
| `GoogleSignin.configure({...})` | Configure in plugin / native config |
|
|
422
|
+
| `GoogleSignin.signIn()` | `login("google")` or `<SocialButton provider="google" />` |
|
|
423
|
+
| `GoogleSignin.signOut()` | `logout()` |
|
|
424
|
+
| `GoogleSignin.getTokens()` | `getAccessToken()` or `refreshToken()` |
|
|
425
|
+
| `GoogleSignin.hasPlayServices()` | `hasPlayServices` from `useAuth()` |
|
|
426
|
+
|
|
427
|
+
**Example migration:**
|
|
428
|
+
|
|
429
|
+
```tsx
|
|
430
|
+
// Before
|
|
431
|
+
import { GoogleSignin } from "@react-native-google-signin/google-signin";
|
|
432
|
+
|
|
433
|
+
await GoogleSignin.signIn();
|
|
434
|
+
const tokens = await GoogleSignin.getTokens();
|
|
435
|
+
|
|
436
|
+
// After
|
|
437
|
+
import { useAuth } from "react-native-nitro-auth";
|
|
438
|
+
|
|
439
|
+
const { login, getAccessToken } = useAuth();
|
|
440
|
+
|
|
441
|
+
await login("google");
|
|
442
|
+
const accessToken = await getAccessToken();
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### 4) Remove manual init
|
|
446
|
+
|
|
447
|
+
If you previously called `GoogleSignin.configure()` at app startup, remove it. Nitro Auth loads configuration from the plugin/native settings at runtime.
|
|
448
|
+
|
|
113
449
|
## Advanced Features
|
|
114
450
|
|
|
451
|
+
### Silent Restore
|
|
452
|
+
|
|
453
|
+
Automatically restore the user session on app startup. This is faster than a full login and works offline if the session is cached.
|
|
454
|
+
|
|
455
|
+
```tsx
|
|
456
|
+
useEffect(() => {
|
|
457
|
+
AuthService.silentRestore();
|
|
458
|
+
}, []);
|
|
459
|
+
```
|
|
460
|
+
|
|
115
461
|
### Global Auth State Listener
|
|
116
462
|
|
|
117
463
|
Subscribe to authentication changes outside of React components:
|
|
@@ -131,40 +477,168 @@ const unsubscribe = AuthService.onAuthStateChanged((user) => {
|
|
|
131
477
|
unsubscribe();
|
|
132
478
|
```
|
|
133
479
|
|
|
480
|
+
### Global Token Refresh Listener
|
|
481
|
+
|
|
482
|
+
Be notified whenever tokens are refreshed automatically (or manually):
|
|
483
|
+
|
|
484
|
+
```ts
|
|
485
|
+
import { AuthService } from "react-native-nitro-auth";
|
|
486
|
+
|
|
487
|
+
const unsubscribe = AuthService.onTokensRefreshed((tokens) => {
|
|
488
|
+
console.log("New tokens:", tokens.accessToken);
|
|
489
|
+
// Update your API client / Apollo links
|
|
490
|
+
});
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Incremental Authorization
|
|
494
|
+
|
|
495
|
+
Request new scopes when you need them without logging the user out:
|
|
496
|
+
|
|
497
|
+
```tsx
|
|
498
|
+
const { requestScopes, revokeScopes, scopes } = useAuth();
|
|
499
|
+
|
|
500
|
+
const handleCalendar = async () => {
|
|
501
|
+
try {
|
|
502
|
+
await requestScopes(["https://www.googleapis.com/auth/calendar.readonly"]);
|
|
503
|
+
console.log("Got calendar access!");
|
|
504
|
+
} catch (e) {
|
|
505
|
+
console.error("Scope request failed");
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Pluggable Storage Adapters
|
|
511
|
+
|
|
512
|
+
Nitro Auth persists the session automatically. By default, it uses secure storage on native (Keychain on iOS, EncryptedSharedPreferences on Android) and `localStorage` on web.
|
|
513
|
+
|
|
514
|
+
#### 1) JS Storage (AsyncStorage, MMKV, etc.)
|
|
515
|
+
|
|
516
|
+
Easily swap the default storage with your preferred library from the JS layer:
|
|
517
|
+
|
|
518
|
+
```ts
|
|
519
|
+
import { AuthService, type JSStorageAdapter } from "react-native-nitro-auth";
|
|
520
|
+
import { MMKV } from "react-native-mmkv";
|
|
521
|
+
|
|
522
|
+
const storage = new MMKV();
|
|
523
|
+
|
|
524
|
+
const mmkvAdapter: JSStorageAdapter = {
|
|
525
|
+
save: (key, value) => storage.set(key, value),
|
|
526
|
+
load: (key) => storage.getString(key),
|
|
527
|
+
remove: (key) => storage.delete(key),
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// Set it once at app startup
|
|
531
|
+
AuthService.setJSStorageAdapter(mmkvAdapter);
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
> [!NOTE]
|
|
535
|
+
> Call `setJSStorageAdapter` before your first `useAuth()` or `AuthService` call so cached values are loaded before UI renders.
|
|
536
|
+
|
|
537
|
+
#### 2) Native Storage (Keychain, etc.)
|
|
538
|
+
|
|
539
|
+
For maximum security, you can implement a native HybridObject (C++, Swift, or Kotlin) and pass it to Nitro. This runs directly in memory at the C++ layer.
|
|
540
|
+
|
|
541
|
+
```ts
|
|
542
|
+
import { AuthService } from "react-native-nitro-auth";
|
|
543
|
+
// Import your native Nitro module
|
|
544
|
+
import { KeychainStorage } from "./native/KeychainStorage";
|
|
545
|
+
|
|
546
|
+
AuthService.setStorageAdapter(KeychainStorage);
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
**Production recommendation:** If you need custom storage policies, auditability, or a different encryption model, provide your own adapter (Keychain, EncryptedSharedPreferences, or a secure JS store). See [Pluggable Storage Adapters](#pluggable-storage-adapters) above.
|
|
550
|
+
|
|
551
|
+
### Production Readiness
|
|
552
|
+
|
|
553
|
+
Nitro Auth is suitable for production use:
|
|
554
|
+
|
|
555
|
+
- **Google Sign-In**: Full support including One-Tap / Sheet, incremental scopes, and token refresh on iOS, Android, and Web.
|
|
556
|
+
- **Apple Sign-In**: Supported on iOS and Web (not available on Android).
|
|
557
|
+
- **Microsoft (Azure AD / B2C)**: Login, incremental scopes, and token refresh are supported on all platforms. Uses PKCE, state, and nonce for security.
|
|
558
|
+
|
|
559
|
+
**Token storage:** By default, tokens are stored in secure platform storage on native (Keychain / EncryptedSharedPreferences) and in `localStorage` on web. On Android API < 23, storage falls back to unencrypted `SharedPreferences`. For high-security web requirements or custom storage needs, configure a [custom storage adapter](#pluggable-storage-adapters).
|
|
560
|
+
|
|
561
|
+
### Logging & Debugging
|
|
562
|
+
|
|
563
|
+
Enable verbose logging to see detailed OAuth flow information in the console:
|
|
564
|
+
|
|
565
|
+
```ts
|
|
566
|
+
import { AuthService } from "react-native-nitro-auth";
|
|
567
|
+
|
|
568
|
+
AuthService.setLoggingEnabled(true);
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Sync Access to Tokens
|
|
572
|
+
|
|
573
|
+
Nitro Auth provides synchronous access to the current state, while still supporting silent refresh:
|
|
574
|
+
|
|
575
|
+
```ts
|
|
576
|
+
// Quick access to what we have in memory
|
|
577
|
+
const user = AuthService.currentUser;
|
|
578
|
+
const scopes = AuthService.grantedScopes;
|
|
579
|
+
|
|
580
|
+
// Async access ensures fresh tokens (will refresh if expired)
|
|
581
|
+
const freshToken = await AuthService.getAccessToken();
|
|
582
|
+
```
|
|
583
|
+
|
|
134
584
|
### Standardized Error Codes
|
|
135
585
|
|
|
136
|
-
Handle failures reliably with predictable error strings:
|
|
586
|
+
Handle failures reliably with predictable error strings. Some flows can surface provider-specific codes (listed below):
|
|
137
587
|
|
|
138
588
|
```ts
|
|
139
589
|
try {
|
|
140
590
|
await login("google");
|
|
141
591
|
} catch (e) {
|
|
142
|
-
|
|
592
|
+
const error = e as Error;
|
|
593
|
+
if (error.message === "cancelled") {
|
|
143
594
|
// User closed the popup/picker
|
|
144
|
-
} else if (
|
|
595
|
+
} else if (error.message === "network_error") {
|
|
145
596
|
// Connection issues
|
|
146
597
|
}
|
|
147
598
|
}
|
|
148
599
|
```
|
|
149
600
|
|
|
150
|
-
|
|
|
151
|
-
|
|
|
152
|
-
| `
|
|
601
|
+
| Error Code | Description |
|
|
602
|
+
| ---------------------- | ---------------------------------------------- |
|
|
603
|
+
| `cancelled` | The user cancelled the sign-in flow |
|
|
604
|
+
| `network_error` | A network error occurred |
|
|
605
|
+
| `configuration_error` | Missing client IDs or invalid setup |
|
|
153
606
|
| `unsupported_provider` | The provider is not supported on this platform |
|
|
607
|
+
| `invalid_state` | PKCE state mismatch (possible CSRF) |
|
|
608
|
+
| `invalid_nonce` | Nonce mismatch in token response |
|
|
609
|
+
| `token_error` | Token exchange failed |
|
|
610
|
+
| `no_id_token` | No `id_token` in token response |
|
|
611
|
+
| `parse_error` | Failed to parse token response |
|
|
612
|
+
| `refresh_failed` | Refresh token flow failed |
|
|
613
|
+
| `unknown` | An unknown error occurred |
|
|
154
614
|
|
|
155
615
|
### Native Error Metadata
|
|
156
616
|
|
|
157
|
-
For more detailed debugging, Nitro Auth captures the raw native error message
|
|
617
|
+
For more detailed debugging, Nitro Auth captures the raw native error message. You can access it from the authenticated user or cast the error:
|
|
158
618
|
|
|
159
619
|
```ts
|
|
620
|
+
// From authenticated user (on success)
|
|
621
|
+
const { user } = useAuth();
|
|
622
|
+
if (user?.underlyingError) {
|
|
623
|
+
console.warn("Auth warning:", user.underlyingError);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// From error (on failure)
|
|
160
627
|
try {
|
|
161
628
|
await login("google");
|
|
162
629
|
} catch (e) {
|
|
163
|
-
|
|
164
|
-
console.log(
|
|
630
|
+
const error = e as Error & { underlyingError?: string };
|
|
631
|
+
console.log("Native error:", error.underlyingError);
|
|
165
632
|
}
|
|
166
633
|
```
|
|
167
634
|
|
|
635
|
+
### Troubleshooting
|
|
636
|
+
|
|
637
|
+
- `configuration_error`: verify client IDs, URL schemes, and redirect URIs are set for the current platform.
|
|
638
|
+
- `invalid_state` or `invalid_nonce`: ensure the redirect URI in your provider console matches your app config exactly.
|
|
639
|
+
- `hasPlayServices` is false: prompt the user to install/update Google Play Services or disable One-Tap.
|
|
640
|
+
- Apple web login fails: confirm `appleWebClientId` is set and your domain is registered with Apple.
|
|
641
|
+
|
|
168
642
|
### Automatic Token Refresh
|
|
169
643
|
|
|
170
644
|
The `getAccessToken()` method automatically checks if the current token is expired (or about to expire) and triggers a silent refresh if possible:
|
|
@@ -176,20 +650,6 @@ const { getAccessToken } = useAuth();
|
|
|
176
650
|
const token = await getAccessToken();
|
|
177
651
|
```
|
|
178
652
|
|
|
179
|
-
### Incremental Authorization
|
|
180
|
-
|
|
181
|
-
Add more scopes after initial login — no need to re-authenticate:
|
|
182
|
-
|
|
183
|
-
```tsx
|
|
184
|
-
const { requestScopes, revokeScopes, scopes } = useAuth();
|
|
185
|
-
|
|
186
|
-
// Request additional scope
|
|
187
|
-
await requestScopes(["https://www.googleapis.com/auth/calendar.readonly"]);
|
|
188
|
-
|
|
189
|
-
// Check granted scopes
|
|
190
|
-
console.log("Granted:", scopes);
|
|
191
|
-
```
|
|
192
|
-
|
|
193
653
|
### Offline Access (Server Auth Code)
|
|
194
654
|
|
|
195
655
|
If you need to access Google APIs from your backend (e.g., Google Calendar integration), you can use the `serverAuthCode`. This code is returned during login and can be exchanged for tokens on your server:
|
|
@@ -205,24 +665,38 @@ if (user?.serverAuthCode) {
|
|
|
205
665
|
|
|
206
666
|
### Custom Storage Adapter
|
|
207
667
|
|
|
208
|
-
By default, Nitro Auth uses
|
|
668
|
+
By default, Nitro Auth uses secure native storage on iOS/Android and `localStorage` on web. You can provide a custom adapter for different security or storage requirements.
|
|
669
|
+
|
|
670
|
+
> [!IMPORTANT]
|
|
671
|
+
> `AuthStorageAdapter` must be implemented as a **native Nitro HybridObject** in C++, Swift, or Kotlin. Plain JavaScript objects are not supported due to Nitro's type system. See [Nitro Hybrid Objects documentation](https://nitro.margelo.com/docs/hybrid-objects) for implementation details.
|
|
672
|
+
|
|
673
|
+
**Example (Swift):**
|
|
674
|
+
|
|
675
|
+
```swift
|
|
676
|
+
class HybridKeychainStorage: HybridAuthStorageAdapterSpec {
|
|
677
|
+
func save(key: String, value: String) {
|
|
678
|
+
// Save to Keychain
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
func load(key: String) -> String? {
|
|
682
|
+
// Load from Keychain
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
func remove(key: String) {
|
|
686
|
+
// Remove from Keychain
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
**Usage (TypeScript):**
|
|
209
692
|
|
|
210
693
|
```ts
|
|
694
|
+
import { NitroModules } from "react-native-nitro-modules";
|
|
211
695
|
import { AuthService, AuthStorageAdapter } from "react-native-nitro-auth";
|
|
212
696
|
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
},
|
|
217
|
-
load: (key) => {
|
|
218
|
-
/* Load from Keychain */
|
|
219
|
-
},
|
|
220
|
-
remove: (key) => {
|
|
221
|
-
/* Clear from Keychain */
|
|
222
|
-
},
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
AuthService.setStorageAdapter(myStorage);
|
|
697
|
+
const keychainStorage =
|
|
698
|
+
NitroModules.createHybridObject<AuthStorageAdapter>("KeychainStorage");
|
|
699
|
+
AuthService.setStorageAdapter(keychainStorage);
|
|
226
700
|
```
|
|
227
701
|
|
|
228
702
|
### Token Refresh Listeners
|
|
@@ -232,9 +706,8 @@ Perfect for updating your API client (e.g., Axios/Fetch) whenever tokens are ref
|
|
|
232
706
|
```ts
|
|
233
707
|
AuthService.onTokensRefreshed((tokens) => {
|
|
234
708
|
console.log("Tokens were updated!", tokens.accessToken);
|
|
235
|
-
apiClient.defaults.headers.common[
|
|
236
|
-
|
|
237
|
-
] = `Bearer ${tokens.accessToken}`;
|
|
709
|
+
apiClient.defaults.headers.common["Authorization"] =
|
|
710
|
+
`Bearer ${tokens.accessToken}`;
|
|
238
711
|
});
|
|
239
712
|
```
|
|
240
713
|
|
|
@@ -249,6 +722,26 @@ await login("google", {
|
|
|
249
722
|
});
|
|
250
723
|
```
|
|
251
724
|
|
|
725
|
+
> [!NOTE]
|
|
726
|
+
> One-Tap requires Google Play Services. You can check `hasPlayServices` from `useAuth()` and show a fallback UI if needed.
|
|
727
|
+
|
|
728
|
+
### Force Account Picker
|
|
729
|
+
|
|
730
|
+
When connecting additional services (like Google Calendar), you may want to let users pick a different account than the one they signed in with. Use `forceAccountPicker` to clear any cached session and show the account picker:
|
|
731
|
+
|
|
732
|
+
```ts
|
|
733
|
+
await login("google", {
|
|
734
|
+
scopes: ["https://www.googleapis.com/auth/calendar.readonly"],
|
|
735
|
+
forceAccountPicker: true, // Always show account picker
|
|
736
|
+
});
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
This is useful for scenarios where:
|
|
740
|
+
|
|
741
|
+
- Users want to connect a different Google account for calendar integration
|
|
742
|
+
- You need to ensure the user can select any account they've added to their device
|
|
743
|
+
- The cached session is interfering with the expected account selection UX
|
|
744
|
+
|
|
252
745
|
## API Reference
|
|
253
746
|
|
|
254
747
|
### useAuth Hook
|
|
@@ -262,18 +755,69 @@ await login("google", {
|
|
|
262
755
|
| `hasPlayServices` | `boolean` | (Android) True if Play Services available |
|
|
263
756
|
| `login` | `(provider, options?) => Promise` | Start login flow |
|
|
264
757
|
| `logout` | `() => void` | Clear session (synchronous) |
|
|
758
|
+
| `silentRestore` | `() => Promise<void>` | Restore session automatically on startup |
|
|
265
759
|
| `requestScopes` | `(scopes) => Promise` | Request additional OAuth scopes |
|
|
760
|
+
| `revokeScopes` | `(scopes) => Promise` | Revoke previously granted scopes |
|
|
266
761
|
| `getAccessToken` | `() => Promise<string?>` | Get current access token (auto-refreshes) |
|
|
267
762
|
| `refreshToken` | `() => Promise<AuthTokens>` | Explicitly refresh and return new tokens |
|
|
268
763
|
|
|
764
|
+
### AuthService
|
|
765
|
+
|
|
766
|
+
| Method | Type | Description |
|
|
767
|
+
| -------------------------- | ----------------------------------------- | -------------------------------------------------- |
|
|
768
|
+
| `login` | `(provider, options?) => Promise<void>` | Start login flow |
|
|
769
|
+
| `logout` | `() => void` | Clear session |
|
|
770
|
+
| `silentRestore` | `() => Promise<void>` | Restore session on startup |
|
|
771
|
+
| `requestScopes` | `(scopes) => Promise<void>` | Request additional OAuth scopes |
|
|
772
|
+
| `revokeScopes` | `(scopes) => Promise<void>` | Revoke previously granted scopes |
|
|
773
|
+
| `getAccessToken` | `() => Promise<string \| undefined>` | Get current access token (auto-refreshes) |
|
|
774
|
+
| `refreshToken` | `() => Promise<AuthTokens>` | Explicitly refresh and return new tokens |
|
|
775
|
+
| `onAuthStateChanged` | `(callback) => () => void` | Subscribe to auth state changes |
|
|
776
|
+
| `onTokensRefreshed` | `(callback) => () => void` | Subscribe to token refresh events |
|
|
777
|
+
| `setLoggingEnabled` | `(enabled: boolean) => void` | Enable or disable verbose logging |
|
|
778
|
+
| `setStorageAdapter` | `(adapter?: AuthStorageAdapter) => void` | Set native storage adapter |
|
|
779
|
+
| `setJSStorageAdapter` | `(adapter?: JSStorageAdapter) => Promise<void>` | Set JS storage adapter |
|
|
780
|
+
|
|
781
|
+
### AuthUser
|
|
782
|
+
|
|
783
|
+
| Field | Type | Description |
|
|
784
|
+
| --------------- | -------------------- | ------------------------------------------------ |
|
|
785
|
+
| `provider` | `"google" \| "apple" \| "microsoft"` | Provider that authenticated the user |
|
|
786
|
+
| `email` | `string?` | User email (if provided) |
|
|
787
|
+
| `name` | `string?` | User display name |
|
|
788
|
+
| `photo` | `string?` | Profile image URL (Google only) |
|
|
789
|
+
| `idToken` | `string?` | OIDC ID token |
|
|
790
|
+
| `accessToken` | `string?` | Access token (if available) |
|
|
791
|
+
| `serverAuthCode`| `string?` | Google server auth code (if configured) |
|
|
792
|
+
| `scopes` | `string[]?` | Granted OAuth scopes |
|
|
793
|
+
| `expirationTime`| `number?` | Token expiration time (ms since epoch) |
|
|
794
|
+
| `underlyingError` | `string?` | Raw native error message |
|
|
795
|
+
|
|
796
|
+
### LoginOptions
|
|
797
|
+
|
|
798
|
+
| Option | Type | Platform | Description |
|
|
799
|
+
| -------------------- | ---------- | -------- | ----------------------------------------------- |
|
|
800
|
+
| `scopes` | `string[]` | All | Required OAuth scopes (default: email, profile) |
|
|
801
|
+
| `loginHint` | `string` | All | Pre-fill email address in the login picker |
|
|
802
|
+
| `useOneTap` | `boolean` | Android | Enable Google One-Tap (Credential Manager) |
|
|
803
|
+
| `useSheet` | `boolean` | iOS | Enable iOS Google Sign-In Sheet |
|
|
804
|
+
| `forceAccountPicker` | `boolean` | All | Always show the account selection screen |
|
|
805
|
+
| `tenant` | `string` | Microsoft | Azure AD tenant (`common`, `organizations`, etc.) |
|
|
806
|
+
| `prompt` | `string` | Microsoft | Prompt behavior (`login`, `consent`, `select_account`, `none`) |
|
|
807
|
+
|
|
269
808
|
### SocialButton Props
|
|
270
809
|
|
|
271
|
-
| Prop
|
|
272
|
-
|
|
|
273
|
-
| `provider`
|
|
274
|
-
| `variant`
|
|
275
|
-
| `
|
|
276
|
-
| `
|
|
810
|
+
| Prop | Type | Default | Description |
|
|
811
|
+
| -------------- | ---------------------------------------------- | ----------- | --------------------------------------------- |
|
|
812
|
+
| `provider` | `"google" \| "apple" \| "microsoft"` | required | Authentication provider |
|
|
813
|
+
| `variant` | `"primary" \| "outline" \| "white" \| "black"` | `"primary"` | Button style variant |
|
|
814
|
+
| `onPress` | `() => void` | — | Custom handler (disables default login) |
|
|
815
|
+
| `onSuccess` | `(user: AuthUser) => void` | — | Called with user data on success (auto-login) |
|
|
816
|
+
| `onError` | `(error: unknown) => void` | — | Called on failure (auto-login) |
|
|
817
|
+
| `disabled` | `boolean` | `false` | Disable button interaction |
|
|
818
|
+
| `style` | `ViewStyle` | — | Custom container styles |
|
|
819
|
+
| `textStyle` | `TextStyle` | — | Custom text styles |
|
|
820
|
+
| `borderRadius` | `number` | `8` | Button border radius |
|
|
277
821
|
|
|
278
822
|
## Platform Support
|
|
279
823
|
|
|
@@ -281,6 +825,7 @@ await login("google", {
|
|
|
281
825
|
| ------------------------- | --- | ------- | --- |
|
|
282
826
|
| Google Sign-In | ✅ | ✅ | ✅ |
|
|
283
827
|
| Apple Sign-In | ✅ | ❌ | ✅ |
|
|
828
|
+
| Microsoft Sign-In | ✅ | ✅ | ✅ |
|
|
284
829
|
| Custom OAuth Scopes | ✅ | ✅ | ✅ |
|
|
285
830
|
| Incremental Authorization | ✅ | ✅ | ✅ |
|
|
286
831
|
| Token Refresh | ✅ | ✅ | ✅ |
|