@chem-po/firebase-native 0.0.17 → 0.0.19
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 +215 -0
- package/lib/commonjs/adapter/auth.js +288 -78
- package/lib/commonjs/adapter/auth.js.map +1 -1
- package/lib/commonjs/components/FirebaseSignIn.js +1 -1
- package/lib/commonjs/components/FirebaseSignIn.js.map +1 -1
- package/lib/commonjs/index.js +11 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/utils/validation.js +71 -0
- package/lib/commonjs/utils/validation.js.map +1 -0
- package/lib/module/adapter/auth.js +288 -78
- package/lib/module/adapter/auth.js.map +1 -1
- package/lib/module/components/FirebaseSignIn.js +1 -1
- package/lib/module/components/FirebaseSignIn.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/validation.js +62 -0
- package/lib/module/utils/validation.js.map +1 -0
- package/lib/typescript/adapter/auth.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/utils/validation.d.ts +21 -0
- package/lib/typescript/utils/validation.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/adapter/auth.ts +263 -70
- package/src/components/FirebaseSignIn.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/utils/validation.ts +85 -0
package/README.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# @chem-po/firebase-native
|
|
2
|
+
|
|
3
|
+
React Native Firebase integration for ChemPo ecosystem.
|
|
4
|
+
|
|
5
|
+
## 🚀 Quick Start
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
Before using this package, ensure your React Native app has:
|
|
10
|
+
|
|
11
|
+
1. **Firebase Project Setup**
|
|
12
|
+
|
|
13
|
+
- Create a Firebase project at https://console.firebase.google.com
|
|
14
|
+
- Enable Authentication with desired providers (Email/Password, Google)
|
|
15
|
+
- Enable Firestore Database
|
|
16
|
+
- Enable Cloud Storage
|
|
17
|
+
|
|
18
|
+
2. **Platform Configuration**
|
|
19
|
+
|
|
20
|
+
#### iOS Setup
|
|
21
|
+
|
|
22
|
+
1. Download `GoogleService-Info.plist` from Firebase Console
|
|
23
|
+
2. Add it to your iOS project root
|
|
24
|
+
3. Configure URL schemes in `ios/[ProjectName]/Info.plist`:
|
|
25
|
+
|
|
26
|
+
```xml
|
|
27
|
+
<key>CFBundleURLTypes</key>
|
|
28
|
+
<array>
|
|
29
|
+
<dict>
|
|
30
|
+
<key>CFBundleURLName</key>
|
|
31
|
+
<string>REVERSED_CLIENT_ID</string>
|
|
32
|
+
<key>CFBundleURLSchemes</key>
|
|
33
|
+
<array>
|
|
34
|
+
<string>YOUR_REVERSED_CLIENT_ID</string>
|
|
35
|
+
</array>
|
|
36
|
+
</dict>
|
|
37
|
+
</array>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Android Setup
|
|
41
|
+
|
|
42
|
+
1. Download `google-services.json` from Firebase Console
|
|
43
|
+
2. Place it in `android/app/google-services.json`
|
|
44
|
+
3. Ensure package name matches Firebase configuration
|
|
45
|
+
|
|
46
|
+
### Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install @chem-po/firebase-native
|
|
50
|
+
# or
|
|
51
|
+
yarn add @chem-po/firebase-native
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Required Peer Dependencies
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm install @react-native-firebase/app @react-native-firebase/auth @react-native-firebase/firestore @react-native-firebase/storage @react-native-firebase/functions @react-native-google-signin/google-signin
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 📱 Configuration
|
|
61
|
+
|
|
62
|
+
### 1. Firebase Initialization
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { getAuth } from '@react-native-firebase/auth'
|
|
66
|
+
import { getFirestore } from '@react-native-firebase/firestore'
|
|
67
|
+
import { getStorage } from '@react-native-firebase/storage'
|
|
68
|
+
import { getFunctions } from '@react-native-firebase/functions'
|
|
69
|
+
import { getFirebaseAdapter } from '@chem-po/firebase-native'
|
|
70
|
+
|
|
71
|
+
// Initialize Firebase services
|
|
72
|
+
const auth = getAuth()
|
|
73
|
+
const firestore = getFirestore()
|
|
74
|
+
const storage = getStorage()
|
|
75
|
+
const functions = getFunctions()
|
|
76
|
+
|
|
77
|
+
// Create backend adapter
|
|
78
|
+
const backendAdapter = getFirebaseAdapter(
|
|
79
|
+
auth,
|
|
80
|
+
firestore,
|
|
81
|
+
storage,
|
|
82
|
+
functions,
|
|
83
|
+
true // Enable two-factor authentication
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 2. Google Authentication Setup
|
|
88
|
+
|
|
89
|
+
**⚠️ REQUIRED**: You must provide your Google Web Client ID:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { GoogleAuthProvider } from '@chem-po/core'
|
|
93
|
+
|
|
94
|
+
// Get this from Firebase Console > Authentication > Sign-in method > Google > Web SDK configuration
|
|
95
|
+
const googleAuthProvider: GoogleAuthProvider = {
|
|
96
|
+
name: 'google',
|
|
97
|
+
webClientId: 'YOUR_GOOGLE_WEB_CLIENT_ID.apps.googleusercontent.com',
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 3. Provider Setup
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { ChempoNativeProvider } from '@chem-po/react-native'
|
|
105
|
+
import { FirebaseSignIn } from '@chem-po/firebase-native'
|
|
106
|
+
|
|
107
|
+
export default function App() {
|
|
108
|
+
return (
|
|
109
|
+
<ChempoNativeProvider backendAdapter={backendAdapter}>
|
|
110
|
+
<FirebaseSignIn googleProvider={googleAuthProvider} />
|
|
111
|
+
</ChempoNativeProvider>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## 🔐 Environment Variables
|
|
117
|
+
|
|
118
|
+
For debug logging (optional):
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
EXPO_PUBLIC_DEBUG=true # Enable debug logging
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 🔧 Configuration Validation
|
|
125
|
+
|
|
126
|
+
Use the built-in validation helper to identify setup issues early:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { validateAndLogAuthConfig } from '@chem-po/firebase-native'
|
|
130
|
+
|
|
131
|
+
// Validate your auth providers configuration
|
|
132
|
+
const providers = [googleAuthProvider] // Your auth providers
|
|
133
|
+
validateAndLogAuthConfig(providers)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
This will output helpful warnings and errors if configuration is missing or incorrect:
|
|
137
|
+
|
|
138
|
+
- ❌ Missing Google webClientId
|
|
139
|
+
- ⚠️ Incorrect webClientId format
|
|
140
|
+
- ⚠️ Missing Firebase configuration files
|
|
141
|
+
|
|
142
|
+
**Tip**: Call this during development to catch configuration issues before they cause runtime errors.
|
|
143
|
+
|
|
144
|
+
## 🚨 Common Issues
|
|
145
|
+
|
|
146
|
+
### "Google web client ID is required"
|
|
147
|
+
|
|
148
|
+
- Ensure you've added the `webClientId` to your Google auth provider
|
|
149
|
+
- Verify the client ID matches your Firebase project configuration
|
|
150
|
+
- Use the validation helper to check your configuration
|
|
151
|
+
|
|
152
|
+
### "No user found"
|
|
153
|
+
|
|
154
|
+
- Check Firebase Authentication is enabled
|
|
155
|
+
- Verify Google Services files are properly configured
|
|
156
|
+
- Ensure bundle ID/package name matches Firebase project
|
|
157
|
+
|
|
158
|
+
### Multi-factor Authentication Issues
|
|
159
|
+
|
|
160
|
+
- Ensure users have enrolled MFA factors via Firebase Console
|
|
161
|
+
- Check that `twoFactorRequired` parameter matches your requirements
|
|
162
|
+
|
|
163
|
+
### Google Play Services Issues
|
|
164
|
+
|
|
165
|
+
- Ensure Google Play Services is installed and up to date
|
|
166
|
+
- Check that your app's package name matches Firebase configuration
|
|
167
|
+
|
|
168
|
+
## 📚 API Reference
|
|
169
|
+
|
|
170
|
+
### getFirebaseAdapter
|
|
171
|
+
|
|
172
|
+
Creates a Firebase backend adapter with authentication, database, and storage.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
getFirebaseAdapter(
|
|
176
|
+
auth: Auth,
|
|
177
|
+
db: Firestore,
|
|
178
|
+
storage: Storage,
|
|
179
|
+
functions: Functions,
|
|
180
|
+
twoFactorRequired: boolean
|
|
181
|
+
): FirebaseAdapter
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### FirebaseSignIn Component
|
|
185
|
+
|
|
186
|
+
Pre-built authentication component with Google Sign-in support.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
<FirebaseSignIn
|
|
190
|
+
googleProvider={googleAuthProvider}
|
|
191
|
+
/>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Configuration Validation
|
|
195
|
+
|
|
196
|
+
Utility functions to validate your Firebase configuration:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
// Validate configuration and get results
|
|
200
|
+
const result = validateAuthConfiguration(providers)
|
|
201
|
+
|
|
202
|
+
// Validate and log results automatically
|
|
203
|
+
validateAndLogAuthConfig(providers)
|
|
204
|
+
|
|
205
|
+
// Custom logging
|
|
206
|
+
logValidationResults(result, 'MyApp')
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## 🤝 Support
|
|
210
|
+
|
|
211
|
+
For issues related to:
|
|
212
|
+
|
|
213
|
+
- Firebase configuration: Check [Firebase Documentation](https://firebase.google.com/docs)
|
|
214
|
+
- React Native Firebase: Check [@react-native-firebase/app](https://rnfirebase.io/)
|
|
215
|
+
- Google Sign-in: Check [@react-native-google-signin](https://github.com/react-native-google-signin/google-signin)
|
|
@@ -6,17 +6,44 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.getFirebaseAuthAdapter = void 0;
|
|
7
7
|
var _auth = require("@react-native-firebase/auth");
|
|
8
8
|
var _googleSignin = require("@react-native-google-signin/google-signin");
|
|
9
|
+
var _process$env;
|
|
10
|
+
const isDebug = typeof process !== 'undefined' && ((_process$env = process.env) === null || _process$env === void 0 ? void 0 : _process$env.EXPO_PUBLIC_DEBUG) === 'true' || false;
|
|
11
|
+
const debugLog = (message, data) => {
|
|
12
|
+
if (isDebug) {
|
|
13
|
+
console.log(`[FirebaseAuth Debug] ${message}`, data || '');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
9
16
|
const providerInitialized = {};
|
|
10
17
|
const getUserWithRole = async user => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
debugLog('Getting user with role', {
|
|
19
|
+
uid: user.uid,
|
|
20
|
+
email: user.email
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
var _user$multiFactor, _user$multiFactor2;
|
|
24
|
+
const {
|
|
25
|
+
claims
|
|
26
|
+
} = await (0, _auth.getIdTokenResult)(user);
|
|
27
|
+
debugLog('Retrieved ID token claims', {
|
|
28
|
+
role: claims.role,
|
|
29
|
+
customClaims: Object.keys(claims)
|
|
30
|
+
});
|
|
31
|
+
const userWithRole = {
|
|
32
|
+
...user,
|
|
33
|
+
role: claims.role ?? 'user',
|
|
34
|
+
multiFactorVerified: !!((_user$multiFactor = user.multiFactor) !== null && _user$multiFactor !== void 0 && _user$multiFactor.enrolledFactors.length)
|
|
35
|
+
};
|
|
36
|
+
debugLog('User with role created', {
|
|
37
|
+
uid: userWithRole.uid,
|
|
38
|
+
role: userWithRole.role,
|
|
39
|
+
multiFactorVerified: userWithRole.multiFactorVerified,
|
|
40
|
+
enrolledFactorsCount: ((_user$multiFactor2 = user.multiFactor) === null || _user$multiFactor2 === void 0 ? void 0 : _user$multiFactor2.enrolledFactors.length) || 0
|
|
41
|
+
});
|
|
42
|
+
return userWithRole;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
debugLog('Error getting user with role', error);
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
20
47
|
};
|
|
21
48
|
const toEnrollmentFactor = hint => {
|
|
22
49
|
if (hint.factorId === _auth.PhoneMultiFactorGenerator.FACTOR_ID) {
|
|
@@ -59,92 +86,203 @@ const toFirebaseFactor = factor => {
|
|
|
59
86
|
throw new Error(`Unsupported factor type: ${factor.factorId ?? 'Missing factor type'}`);
|
|
60
87
|
};
|
|
61
88
|
const sendMultiFactorCode = async (auth, factor, resolver) => {
|
|
89
|
+
debugLog('Sending multi-factor code', {
|
|
90
|
+
factorType: factor.type,
|
|
91
|
+
factorUid: factor.uid
|
|
92
|
+
});
|
|
62
93
|
const sessionId = resolver.session;
|
|
63
94
|
// const verificationId = await new PhoneAuthProvider(auth).verifyPhoneNumber(phoneSignInFactor, sessionId)
|
|
64
95
|
if (factor.type === 'phone') {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
96
|
+
try {
|
|
97
|
+
const verificationId = await auth.verifyPhoneNumberWithMultiFactorInfo(toFirebaseFactor(factor), sessionId);
|
|
98
|
+
debugLog('Multi-factor code sent successfully', {
|
|
99
|
+
verificationId: verificationId.substring(0, 10) + '...'
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
verificationId,
|
|
103
|
+
factor,
|
|
104
|
+
resolver
|
|
105
|
+
};
|
|
106
|
+
} catch (error) {
|
|
107
|
+
debugLog('Error sending multi-factor code', error);
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
71
110
|
}
|
|
72
111
|
throw new Error(`Unsupported factor type: ${factor.type ?? 'Missing factor type'}`);
|
|
73
112
|
};
|
|
74
113
|
const getEnrolledFactors = async (auth, error) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
114
|
+
debugLog('Getting enrolled factors from error', {
|
|
115
|
+
errorCode: error === null || error === void 0 ? void 0 : error.code
|
|
116
|
+
});
|
|
117
|
+
try {
|
|
118
|
+
const resolver = (0, _auth.getMultiFactorResolver)(auth, error);
|
|
119
|
+
debugLog('Multi-factor resolver created', {
|
|
120
|
+
hintsCount: resolver.hints.length
|
|
121
|
+
});
|
|
122
|
+
if (resolver.hints.length === 0) {
|
|
123
|
+
debugLog('No enrolled factors found');
|
|
124
|
+
throw new Error('No multi-factor verification methods found, please enroll one on the website');
|
|
125
|
+
}
|
|
126
|
+
const enrollmentFactors = resolver.hints.map(toEnrollmentFactor);
|
|
127
|
+
debugLog('Enrollment factors mapped', {
|
|
128
|
+
factors: enrollmentFactors.map(f => ({
|
|
129
|
+
type: f.type,
|
|
130
|
+
uid: f.uid
|
|
131
|
+
}))
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
enrollmentFactors,
|
|
135
|
+
multiFactorResolver: resolver
|
|
136
|
+
};
|
|
137
|
+
} catch (error) {
|
|
138
|
+
debugLog('Error getting enrolled factors', error);
|
|
139
|
+
throw error;
|
|
78
140
|
}
|
|
79
|
-
return {
|
|
80
|
-
enrollmentFactors: resolver.hints.map(toEnrollmentFactor),
|
|
81
|
-
multiFactorResolver: resolver
|
|
82
|
-
};
|
|
83
141
|
};
|
|
84
142
|
const verifyMultiFactor = async (verification, code) => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
143
|
+
debugLog('Verifying multi-factor code', {
|
|
144
|
+
factorType: verification.factor.type,
|
|
145
|
+
codeLength: code.length
|
|
146
|
+
});
|
|
147
|
+
try {
|
|
148
|
+
var _userCredential$user;
|
|
149
|
+
const credential = await _auth.PhoneAuthProvider.credential(verification.verificationId, code);
|
|
150
|
+
debugLog('Phone credential created');
|
|
151
|
+
const assertion = _auth.PhoneMultiFactorGenerator.assertion(credential);
|
|
152
|
+
debugLog('Multi-factor assertion created');
|
|
153
|
+
const resolver = verification.resolver;
|
|
154
|
+
if (!resolver) {
|
|
155
|
+
debugLog('Multi-factor resolver not found');
|
|
156
|
+
throw new Error('Internal error signing in with two factor: resolver not found');
|
|
157
|
+
}
|
|
158
|
+
const userCredential = await resolver.resolveSignIn(assertion);
|
|
159
|
+
debugLog('Multi-factor sign-in resolved', {
|
|
160
|
+
uid: (_userCredential$user = userCredential.user) === null || _userCredential$user === void 0 ? void 0 : _userCredential$user.uid
|
|
161
|
+
});
|
|
162
|
+
const user = userCredential.user;
|
|
163
|
+
if (!user) {
|
|
164
|
+
debugLog('No user found after multi-factor resolution');
|
|
165
|
+
throw new Error('No user found');
|
|
166
|
+
}
|
|
167
|
+
const userWithRole = await getUserWithRole(user);
|
|
168
|
+
debugLog('Multi-factor verification completed successfully');
|
|
169
|
+
return {
|
|
170
|
+
user: userWithRole
|
|
171
|
+
};
|
|
172
|
+
} catch (error) {
|
|
173
|
+
debugLog('Error verifying multi-factor', error);
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
95
176
|
};
|
|
96
177
|
const handleSignInError = async error => {
|
|
178
|
+
debugLog('Handling sign-in error', {
|
|
179
|
+
code: error === null || error === void 0 ? void 0 : error.code,
|
|
180
|
+
message: error === null || error === void 0 ? void 0 : error.message
|
|
181
|
+
});
|
|
97
182
|
if (error.code === 'auth/multi-factor-auth-required') {
|
|
183
|
+
debugLog('Multi-factor authentication required');
|
|
98
184
|
return {
|
|
99
185
|
requestArgs: error
|
|
100
186
|
};
|
|
101
187
|
}
|
|
188
|
+
debugLog('Re-throwing sign-in error');
|
|
102
189
|
throw error;
|
|
103
190
|
};
|
|
104
191
|
const initializeProvider = async provider => {
|
|
105
|
-
|
|
192
|
+
debugLog('Initializing provider', {
|
|
193
|
+
name: provider.name,
|
|
194
|
+
alreadyInitialized: providerInitialized[provider.name]
|
|
195
|
+
});
|
|
196
|
+
if (providerInitialized[provider.name]) {
|
|
197
|
+
debugLog('Provider already initialized, skipping');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
106
200
|
switch (provider.name) {
|
|
107
201
|
case 'google':
|
|
202
|
+
debugLog('Initializing Google provider', {
|
|
203
|
+
webClientId: !!provider.webClientId
|
|
204
|
+
});
|
|
108
205
|
if (!provider.webClientId) {
|
|
109
|
-
|
|
206
|
+
debugLog('Google web client ID missing');
|
|
207
|
+
throw new Error('Google web client ID is required when using Google Auth. ' + 'Get your webClientId from Firebase Console > Authentication > Sign-in method > Google > Web SDK configuration. ' + 'Then provide it in your GoogleAuthProvider: { name: "google", webClientId: "YOUR_CLIENT_ID" }');
|
|
208
|
+
}
|
|
209
|
+
try {
|
|
210
|
+
await _googleSignin.GoogleSignin.hasPlayServices({
|
|
211
|
+
showPlayServicesUpdateDialog: true
|
|
212
|
+
});
|
|
213
|
+
debugLog('Google Play Services available');
|
|
214
|
+
_googleSignin.GoogleSignin.configure({
|
|
215
|
+
webClientId: provider.webClientId
|
|
216
|
+
});
|
|
217
|
+
debugLog('Google Sign-In configured successfully');
|
|
218
|
+
} catch (error) {
|
|
219
|
+
debugLog('Error initializing Google provider', error);
|
|
220
|
+
if (error instanceof Error && error.message.includes('UNAVAILABLE')) {
|
|
221
|
+
throw new Error('Google Play Services is not available or needs to be updated. ' + 'Please ensure Google Play Services is installed and up to date on this device.');
|
|
222
|
+
}
|
|
223
|
+
throw error;
|
|
110
224
|
}
|
|
111
|
-
await _googleSignin.GoogleSignin.hasPlayServices({
|
|
112
|
-
showPlayServicesUpdateDialog: true
|
|
113
|
-
});
|
|
114
|
-
_googleSignin.GoogleSignin.configure({
|
|
115
|
-
webClientId: provider.webClientId
|
|
116
|
-
});
|
|
117
225
|
break;
|
|
118
226
|
case 'email':
|
|
227
|
+
debugLog('Email provider initialization (no special setup required)');
|
|
119
228
|
// Native SDK doesn't need special initialization
|
|
120
229
|
break;
|
|
121
230
|
default:
|
|
231
|
+
debugLog('Unsupported provider', {
|
|
232
|
+
name: provider.name
|
|
233
|
+
});
|
|
122
234
|
throw new Error(`Unsupported provider: ${provider.name}`);
|
|
123
235
|
}
|
|
124
236
|
providerInitialized[provider.name] = true;
|
|
237
|
+
debugLog('Provider initialization completed', {
|
|
238
|
+
name: provider.name
|
|
239
|
+
});
|
|
125
240
|
};
|
|
126
241
|
const handleInitialLogin = async (userCredential, twoFactorRequired) => {
|
|
242
|
+
var _userCredential$user2, _userCredential$user3;
|
|
243
|
+
debugLog('Handling initial login', {
|
|
244
|
+
uid: (_userCredential$user2 = userCredential.user) === null || _userCredential$user2 === void 0 ? void 0 : _userCredential$user2.uid,
|
|
245
|
+
twoFactorRequired,
|
|
246
|
+
enrolledFactorsCount: ((_userCredential$user3 = userCredential.user) === null || _userCredential$user3 === void 0 || (_userCredential$user3 = _userCredential$user3.multiFactor) === null || _userCredential$user3 === void 0 ? void 0 : _userCredential$user3.enrolledFactors.length) || 0
|
|
247
|
+
});
|
|
127
248
|
const user = userCredential.user;
|
|
128
|
-
if (!user)
|
|
249
|
+
if (!user) {
|
|
250
|
+
debugLog('No user found in credential');
|
|
251
|
+
throw new Error('No user found');
|
|
252
|
+
}
|
|
129
253
|
if (twoFactorRequired) {
|
|
254
|
+
debugLog('Two-factor authentication is required but user has no enrolled factors');
|
|
130
255
|
throw new Error('This app requires two factor authentication, please enroll a factor on the website and try again');
|
|
131
256
|
}
|
|
257
|
+
const userWithRole = await getUserWithRole(user);
|
|
258
|
+
debugLog('Initial login completed successfully');
|
|
132
259
|
return {
|
|
133
|
-
user:
|
|
260
|
+
user: userWithRole
|
|
134
261
|
};
|
|
135
262
|
};
|
|
136
263
|
const loginWithGoogle = async (auth, twoFactorRequired) => {
|
|
264
|
+
debugLog('Starting Google sign-in', {
|
|
265
|
+
twoFactorRequired
|
|
266
|
+
});
|
|
137
267
|
try {
|
|
138
|
-
var _signInResult$data;
|
|
268
|
+
var _signInResult$data, _signInResult$data2;
|
|
269
|
+
debugLog('Calling GoogleSignin.signIn()');
|
|
139
270
|
const signInResult = await _googleSignin.GoogleSignin.signIn();
|
|
140
|
-
|
|
271
|
+
debugLog('Google sign-in result received', {
|
|
272
|
+
hasIdToken: !!((_signInResult$data = signInResult.data) !== null && _signInResult$data !== void 0 && _signInResult$data.idToken)
|
|
273
|
+
});
|
|
274
|
+
const idToken = (_signInResult$data2 = signInResult.data) === null || _signInResult$data2 === void 0 ? void 0 : _signInResult$data2.idToken;
|
|
141
275
|
if (!idToken) {
|
|
276
|
+
debugLog('No ID token found in Google sign-in result');
|
|
142
277
|
throw new Error('No ID token found');
|
|
143
278
|
}
|
|
279
|
+
debugLog('Creating Google credential');
|
|
144
280
|
const googleCredential = _auth.GoogleAuthProvider.credential(idToken);
|
|
281
|
+
debugLog('Signing in with Google credential');
|
|
145
282
|
const userCredential = await (0, _auth.signInWithCredential)(auth, googleCredential);
|
|
146
283
|
return await handleInitialLogin(userCredential, twoFactorRequired);
|
|
147
284
|
} catch (error) {
|
|
285
|
+
debugLog('Error in Google sign-in', error);
|
|
148
286
|
return await handleSignInError(error);
|
|
149
287
|
}
|
|
150
288
|
};
|
|
@@ -152,70 +290,142 @@ const getLoginWithPassword = (auth, twoFactorRequired) => async (provider, {
|
|
|
152
290
|
email,
|
|
153
291
|
password
|
|
154
292
|
}) => {
|
|
293
|
+
debugLog('Starting email/password sign-in', {
|
|
294
|
+
provider: provider.name,
|
|
295
|
+
email,
|
|
296
|
+
twoFactorRequired
|
|
297
|
+
});
|
|
155
298
|
await initializeProvider(provider);
|
|
156
299
|
try {
|
|
300
|
+
var _userCredential$user4;
|
|
301
|
+
debugLog('Calling signInWithEmailAndPassword');
|
|
157
302
|
const userCredential = await (0, _auth.signInWithEmailAndPassword)(auth, email, password);
|
|
303
|
+
debugLog('Email/password sign-in successful', {
|
|
304
|
+
uid: (_userCredential$user4 = userCredential.user) === null || _userCredential$user4 === void 0 ? void 0 : _userCredential$user4.uid
|
|
305
|
+
});
|
|
158
306
|
return await handleInitialLogin(userCredential, twoFactorRequired);
|
|
159
307
|
} catch (error) {
|
|
308
|
+
debugLog('Error in email/password sign-in', error);
|
|
160
309
|
return await handleSignInError(error);
|
|
161
310
|
}
|
|
162
311
|
};
|
|
163
312
|
const getLoginWithPopup = (auth, twoFactorRequired) => async provider => {
|
|
313
|
+
debugLog('Starting popup sign-in', {
|
|
314
|
+
provider: provider.name,
|
|
315
|
+
twoFactorRequired
|
|
316
|
+
});
|
|
164
317
|
await initializeProvider(provider);
|
|
165
318
|
switch (provider.name) {
|
|
166
319
|
case 'google':
|
|
167
320
|
return loginWithGoogle(auth, twoFactorRequired);
|
|
168
321
|
default:
|
|
322
|
+
debugLog('Unsupported popup provider', {
|
|
323
|
+
name: provider.name
|
|
324
|
+
});
|
|
169
325
|
throw new Error(`Unsupported provider: ${provider.name}`);
|
|
170
326
|
}
|
|
171
327
|
};
|
|
172
328
|
const getLoginWithToken = (auth, twoFactorRequired) => async (provider, token) => {
|
|
329
|
+
debugLog('Starting token sign-in', {
|
|
330
|
+
provider: provider.name,
|
|
331
|
+
tokenLength: token.length,
|
|
332
|
+
twoFactorRequired
|
|
333
|
+
});
|
|
173
334
|
await initializeProvider(provider);
|
|
174
335
|
try {
|
|
336
|
+
var _userCredential$user5;
|
|
337
|
+
debugLog('Calling signInWithCustomToken');
|
|
175
338
|
const userCredential = await (0, _auth.signInWithCustomToken)(auth, token);
|
|
339
|
+
debugLog('Token sign-in successful', {
|
|
340
|
+
uid: (_userCredential$user5 = userCredential.user) === null || _userCredential$user5 === void 0 ? void 0 : _userCredential$user5.uid
|
|
341
|
+
});
|
|
176
342
|
return await handleInitialLogin(userCredential, twoFactorRequired);
|
|
177
343
|
} catch (error) {
|
|
344
|
+
debugLog('Error in token sign-in', error);
|
|
178
345
|
return await handleSignInError(error);
|
|
179
346
|
}
|
|
180
347
|
};
|
|
181
348
|
const resetPassword = async (auth, provider, usernameOrEmail) => {
|
|
349
|
+
debugLog('Starting password reset', {
|
|
350
|
+
provider: provider.name,
|
|
351
|
+
email: usernameOrEmail
|
|
352
|
+
});
|
|
182
353
|
await initializeProvider(provider);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return sendMultiFactorCode(auth, ...args);
|
|
201
|
-
},
|
|
202
|
-
getEnrolledFactors: (...args) => {
|
|
203
|
-
return getEnrolledFactors(auth, ...args);
|
|
204
|
-
},
|
|
205
|
-
logout: async () => {
|
|
206
|
-
await (0, _auth.signOut)(auth);
|
|
207
|
-
},
|
|
208
|
-
subscribeToUser: callback => {
|
|
209
|
-
return (0, _auth.onAuthStateChanged)(auth, user => {
|
|
354
|
+
try {
|
|
355
|
+
await (0, _auth.sendPasswordResetEmail)(auth, usernameOrEmail);
|
|
356
|
+
debugLog('Password reset email sent successfully');
|
|
357
|
+
} catch (error) {
|
|
358
|
+
debugLog('Error sending password reset email', error);
|
|
359
|
+
throw error;
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
const getFirebaseAuthAdapter = (auth, twoFactorRequired) => {
|
|
363
|
+
debugLog('Creating Firebase Auth Adapter', {
|
|
364
|
+
twoFactorRequired
|
|
365
|
+
});
|
|
366
|
+
return {
|
|
367
|
+
twoFactorRequired,
|
|
368
|
+
getCurrentUser: async () => {
|
|
369
|
+
debugLog('Getting current user');
|
|
370
|
+
const user = auth.currentUser;
|
|
210
371
|
if (!user) {
|
|
211
|
-
|
|
212
|
-
return;
|
|
372
|
+
debugLog('No current user found');
|
|
373
|
+
return null;
|
|
213
374
|
}
|
|
214
|
-
|
|
215
|
-
|
|
375
|
+
debugLog('Current user found', {
|
|
376
|
+
uid: user.uid,
|
|
377
|
+
email: user.email
|
|
216
378
|
});
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
379
|
+
return getUserWithRole(user);
|
|
380
|
+
},
|
|
381
|
+
loginWithPassword: getLoginWithPassword(auth, twoFactorRequired),
|
|
382
|
+
loginWithPopup: getLoginWithPopup(auth, twoFactorRequired),
|
|
383
|
+
loginWithToken: getLoginWithToken(auth, twoFactorRequired),
|
|
384
|
+
resetPassword: (...args) => {
|
|
385
|
+
return resetPassword(auth, ...args);
|
|
386
|
+
},
|
|
387
|
+
verifyMultiFactor,
|
|
388
|
+
sendMultiFactorCode: (...args) => {
|
|
389
|
+
return sendMultiFactorCode(auth, ...args);
|
|
390
|
+
},
|
|
391
|
+
getEnrolledFactors: (...args) => {
|
|
392
|
+
return getEnrolledFactors(auth, ...args);
|
|
393
|
+
},
|
|
394
|
+
logout: async () => {
|
|
395
|
+
debugLog('Starting logout');
|
|
396
|
+
try {
|
|
397
|
+
await (0, _auth.signOut)(auth);
|
|
398
|
+
debugLog('Logout completed successfully');
|
|
399
|
+
} catch (error) {
|
|
400
|
+
debugLog('Error during logout', error);
|
|
401
|
+
throw error;
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
subscribeToUser: callback => {
|
|
405
|
+
debugLog('Setting up user subscription');
|
|
406
|
+
return (0, _auth.onAuthStateChanged)(auth, user => {
|
|
407
|
+
if (!user) {
|
|
408
|
+
debugLog('User state changed: signed out');
|
|
409
|
+
callback(null);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
debugLog('User state changed: user signed in', {
|
|
413
|
+
uid: user.uid,
|
|
414
|
+
email: user.email
|
|
415
|
+
});
|
|
416
|
+
getUserWithRole(user).then(result => {
|
|
417
|
+
debugLog('User subscription callback completed', {
|
|
418
|
+
uid: result.uid,
|
|
419
|
+
role: result.role
|
|
420
|
+
});
|
|
421
|
+
callback(result);
|
|
422
|
+
}).catch(error => {
|
|
423
|
+
debugLog('Error in user subscription callback', error);
|
|
424
|
+
callback(null);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
};
|
|
220
430
|
exports.getFirebaseAuthAdapter = getFirebaseAuthAdapter;
|
|
221
431
|
//# sourceMappingURL=auth.js.map
|