strapi-plugin-firebase-authentication 1.6.0 → 1.7.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 +218 -450
- package/dist/_chunks/{App-DjeXCYLI.js → App-CSFciBSN.js} +2 -2
- package/dist/_chunks/{App-DWb7aV0a.mjs → App-Dzl5W6YR.mjs} +2 -2
- package/dist/_chunks/{api-BlWOjGIx.mjs → api-BXpBvqeN.mjs} +1 -1
- package/dist/_chunks/{api-B6slsjut.js → api-C0GYp4ji.js} +1 -1
- package/dist/_chunks/{index-CD2ZZc6l.js → index-BEmqy-R3.js} +2 -2
- package/dist/_chunks/{index-jxnRtalg.mjs → index-CCa5Fl4r.mjs} +26 -20
- package/dist/_chunks/{index-DLFklFzP.js → index-CfYs8WkU.js} +26 -20
- package/dist/_chunks/{index-BFe-pIBw.mjs → index-K_RiV2x9.mjs} +2 -2
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +1 -3
- package/dist/server/index.mjs +4 -4
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -4,93 +4,67 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/strapi-plugin-firebase-authentication)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
**Authentication:**
|
|
41
|
-
|
|
42
|
-
- `POST /api/firebase-authentication` - Exchange Firebase token for Strapi JWT
|
|
43
|
-
- `POST /api/firebase-authentication/emailLogin` - Direct email/password login
|
|
44
|
-
- `POST /api/firebase-authentication/forgotPassword` - Request password reset
|
|
45
|
-
- `POST /api/firebase-authentication/resetPassword` - Authenticated password change (requires JWT)
|
|
46
|
-
- `POST /api/firebase-authentication/requestMagicLink` - Passwordless login
|
|
47
|
-
- `GET /api/firebase-authentication/config` - Get public configuration
|
|
48
|
-
|
|
49
|
-
### Minimal Configuration
|
|
50
|
-
|
|
51
|
-
```javascript
|
|
52
|
-
// config/plugins.js
|
|
53
|
-
module.exports = () => ({
|
|
54
|
-
"firebase-authentication": {
|
|
55
|
-
enabled: true,
|
|
56
|
-
config: {
|
|
57
|
-
FIREBASE_JSON_ENCRYPTION_KEY: process.env.FIREBASE_JSON_ENCRYPTION_KEY,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
});
|
|
7
|
+
**Use Firebase Authentication with Strapi v5** - without building custom auth logic.
|
|
8
|
+
|
|
9
|
+
Firebase handles user authentication (Google, Apple, Phone, Email, Magic Link). This plugin bridges Firebase to Strapi by verifying tokens, automatically creating/syncing users, and returning Strapi JWTs for API access. Your users authenticate once with Firebase and get full access to your Strapi content based on roles and permissions.
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
```mermaid
|
|
14
|
+
sequenceDiagram
|
|
15
|
+
participant App as Your App
|
|
16
|
+
participant Firebase as Firebase Auth
|
|
17
|
+
participant Strapi as Strapi + Plugin
|
|
18
|
+
|
|
19
|
+
rect rgb(240, 248, 255)
|
|
20
|
+
Note over App,Firebase: Authentication
|
|
21
|
+
App->>Firebase: 1. Sign in (Google, Apple, Phone, Email...)
|
|
22
|
+
Firebase-->>App: 2. Returns Firebase ID Token
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
rect rgb(240, 255, 240)
|
|
26
|
+
Note over App,Strapi: Token Exchange
|
|
27
|
+
App->>Strapi: 3. POST /api/firebase-authentication { idToken }
|
|
28
|
+
Strapi->>Firebase: 4. Verify token
|
|
29
|
+
Firebase-->>Strapi: 5. Token valid
|
|
30
|
+
Note over Strapi: 6. Find or create Strapi user
|
|
31
|
+
Strapi-->>App: 7. Returns { user, jwt }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
rect rgb(255, 250, 240)
|
|
35
|
+
Note over App,Strapi: API Access
|
|
36
|
+
App->>Strapi: 8. GET /api/content (Bearer jwt)
|
|
37
|
+
Strapi-->>App: 9. Protected data
|
|
38
|
+
end
|
|
61
39
|
```
|
|
62
40
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
41
|
+
**Summary:**
|
|
42
|
+
|
|
43
|
+
- **Steps 1-2:** User authenticates with Firebase (you handle this with Firebase SDK)
|
|
44
|
+
- **Steps 3-7:** You send the Firebase token to this plugin, it verifies with Firebase, finds or creates a Strapi user, and returns a Strapi JWT
|
|
45
|
+
- **Steps 8-9:** You use the Strapi JWT for all API calls to access protected content
|
|
46
|
+
|
|
47
|
+
## Features
|
|
67
48
|
|
|
68
|
-
|
|
49
|
+
- 🔐 **Multi-Provider Auth** - Support for Google, Apple, Email/Password, Phone, and Magic Link. All providers are verified server-side via Firebase Admin SDK and mapped to a single Strapi user using Firebase UID as the primary link. User signs in with Google on mobile, later with Apple on web - same Strapi user, same roles and permissions.
|
|
69
50
|
|
|
70
|
-
|
|
71
|
-
2. **Configure:** Add plugin config to `config/plugins.js`
|
|
72
|
-
3. **Build:** `yarn build && yarn develop`
|
|
73
|
-
4. **Upload:** Settings → Firebase Authentication → Upload service account JSON
|
|
74
|
-
5. **Permissions:** Settings → Users & Permissions → Public → `firebase-authentication.authenticate` ✓
|
|
51
|
+
- 🔄 **Auto User Sync** - On first authentication, the plugin automatically creates a Strapi user with the default `authenticated` role. Existing users are matched by Firebase UID first, then by email, then by phone number. Profile data (name, email, phone) is synced from the Firebase token. No manual user creation needed - scales to thousands of users.
|
|
75
52
|
|
|
76
|
-
|
|
53
|
+
- 📱 **Phone-Only Auth** - For apps where email isn't required (common in emerging markets), the plugin generates unique placeholder emails using configurable patterns with tokens: `{randomString}`, `{phoneNumber}`, `{timestamp}`. Example: `{randomString}@phone-user.local` becomes `a1b2c3d4@phone-user.local`. Phone users get full access to Strapi's permission system.
|
|
77
54
|
|
|
78
|
-
- **
|
|
79
|
-
- **User Management:** Plugins → Firebase Authentication
|
|
55
|
+
- 🔑 **Password Reset** - Two flows available: `POST /forgotPassword` sends a branded reset email via your Strapi email provider (SendGrid, Mailgun, etc.), and `POST /resetPassword` allows authenticated password changes. Includes customizable email templates, configurable reset URLs, regex password validation, and optional Firebase custom tokens for auto-login after reset.
|
|
80
56
|
|
|
81
|
-
|
|
57
|
+
- ✨ **Magic Link** - Passwordless authentication via `POST /requestMagicLink`. Generates a secure one-time JWT token with configurable expiry (1-72 hours), sends via your Strapi email provider, and returns a Strapi JWT on verification. Tokens are invalidated after use. Perfect for B2B apps where users prefer "email me a login link" over passwords.
|
|
82
58
|
|
|
83
|
-
|
|
59
|
+
- 🛡️ **Encrypted Config** - Firebase service account JSON (contains private keys) is encrypted with AES-256 using your `FIREBASE_JSON_ENCRYPTION_KEY` before storing in the database. Decrypted only in memory at runtime - never exposed in API responses, logs, or database backups. Meets enterprise security requirements.
|
|
84
60
|
|
|
85
|
-
|
|
61
|
+
- 📊 **Activity Logging** - Tracks all authentication events with full context: user ID, Firebase UID, action type (login, token exchange, password reset, account deletion), IP address, and timestamp. Automatic cleanup via `FIREBASE_ACTIVITY_LOG_RETENTION_DAYS`. Essential for security audits, debugging auth issues, and compliance requirements.
|
|
86
62
|
|
|
87
|
-
|
|
63
|
+
- 🎛️ **Admin Panel** - Full Firebase user management UI integrated into Strapi admin at Plugins > Firebase Authentication. Search users by email/phone/UID, view linked Strapi accounts, edit user details, trigger password reset emails, send verification emails, and delete users from Firebase, Strapi, or both. No need to switch to Firebase Console.
|
|
88
64
|
|
|
89
|
-
|
|
90
|
-
- Firebase project with Authentication enabled ([Create one](https://console.firebase.google.com/))
|
|
91
|
-
- Node.js 18+ and npm/yarn installed
|
|
65
|
+
## Quick Start
|
|
92
66
|
|
|
93
|
-
###
|
|
67
|
+
### 1. Install
|
|
94
68
|
|
|
95
69
|
```bash
|
|
96
70
|
yarn add strapi-plugin-firebase-authentication
|
|
@@ -98,26 +72,9 @@ yarn add strapi-plugin-firebase-authentication
|
|
|
98
72
|
npm install strapi-plugin-firebase-authentication
|
|
99
73
|
```
|
|
100
74
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
### Step 2: Create Encryption Key
|
|
106
|
-
|
|
107
|
-
Generate a secure 32+ character encryption key for storing Firebase credentials:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
# Generate a random key (save this!)
|
|
111
|
-
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**Common Mistake:** Using a weak or short key. The key MUST be at least 32 characters.
|
|
115
|
-
|
|
116
|
-
---
|
|
75
|
+
### 2. Configure
|
|
117
76
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
Create or edit `config/plugins.js`:
|
|
77
|
+
Create or update `config/plugins.js`:
|
|
121
78
|
|
|
122
79
|
```javascript
|
|
123
80
|
module.exports = () => ({
|
|
@@ -130,297 +87,212 @@ module.exports = () => ({
|
|
|
130
87
|
});
|
|
131
88
|
```
|
|
132
89
|
|
|
133
|
-
Add to `.env
|
|
90
|
+
Add to `.env`:
|
|
134
91
|
|
|
135
92
|
```bash
|
|
136
|
-
|
|
93
|
+
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
94
|
+
FIREBASE_JSON_ENCRYPTION_KEY=your-32-character-minimum-key-here
|
|
137
95
|
```
|
|
138
96
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
---
|
|
142
|
-
|
|
143
|
-
### Step 4: Build and Start
|
|
97
|
+
### 3. Build & Start
|
|
144
98
|
|
|
145
99
|
```bash
|
|
146
|
-
yarn build
|
|
147
|
-
yarn develop
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
**What happens:**
|
|
151
|
-
|
|
152
|
-
- Plugin compiles (admin + server)
|
|
153
|
-
- Strapi restarts with plugin enabled
|
|
154
|
-
- "Firebase Authentication" appears in Plugins sidebar
|
|
155
|
-
|
|
156
|
-
**Verify:** Check console output for:
|
|
157
|
-
|
|
158
|
-
```
|
|
159
|
-
✔ Building admin panel (XX.Xs)
|
|
160
|
-
Firebase Authentication plugin initialized
|
|
100
|
+
yarn build && yarn develop
|
|
161
101
|
```
|
|
162
102
|
|
|
163
|
-
|
|
103
|
+
### 4. Upload Firebase Config
|
|
164
104
|
|
|
165
|
-
|
|
105
|
+
1. Go to [Firebase Console](https://console.firebase.google.com/) → Project Settings → Service Accounts
|
|
106
|
+
2. Click **Generate New Private Key** (downloads JSON)
|
|
107
|
+
3. In Strapi: **Settings → Firebase Authentication → Upload Configuration**
|
|
108
|
+
4. Restart Strapi after uploading
|
|
166
109
|
|
|
167
|
-
###
|
|
110
|
+
### 5. Enable Permissions
|
|
168
111
|
|
|
169
|
-
|
|
170
|
-
2. Select your project
|
|
171
|
-
3. Navigate to: **Project Settings** (⚙️ icon) → **Service Accounts** tab
|
|
172
|
-
4. Click **"Generate New Private Key"**
|
|
173
|
-
5. Download and save the JSON file securely (you'll upload this next)
|
|
112
|
+
**Settings → Users & Permissions → Roles → Public**
|
|
174
113
|
|
|
175
|
-
|
|
114
|
+
Enable: `firebase-authentication` → `authenticate` ✓
|
|
176
115
|
|
|
177
|
-
|
|
116
|
+
## API Reference
|
|
178
117
|
|
|
179
|
-
###
|
|
118
|
+
### Authentication Endpoints
|
|
180
119
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
120
|
+
| Method | Endpoint | Purpose |
|
|
121
|
+
| ------ | ----------------------------------------------- | -------------------------------------- |
|
|
122
|
+
| POST | `/api/firebase-authentication` | Exchange Firebase token for Strapi JWT |
|
|
123
|
+
| POST | `/api/firebase-authentication/emailLogin` | Direct email/password login |
|
|
124
|
+
| POST | `/api/firebase-authentication/forgotPassword` | Request password reset email |
|
|
125
|
+
| POST | `/api/firebase-authentication/requestMagicLink` | Request passwordless login link |
|
|
126
|
+
| GET | `/api/firebase-authentication/config` | Get public configuration |
|
|
186
127
|
|
|
187
|
-
|
|
128
|
+
### Token Exchange (Main Endpoint)
|
|
188
129
|
|
|
130
|
+
```bash
|
|
131
|
+
POST /api/firebase-authentication
|
|
132
|
+
Content-Type: application/json
|
|
133
|
+
|
|
134
|
+
{
|
|
135
|
+
"idToken": "firebase-id-token-here",
|
|
136
|
+
"profileMetaData": { // Optional
|
|
137
|
+
"firstName": "John",
|
|
138
|
+
"lastName": "Doe"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
189
141
|
```
|
|
190
|
-
Firebase Admin SDK initialized successfully
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
**If initialization fails:** Check [Troubleshooting](#troubleshooting) section.
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
### Step 7: Configure Permissions
|
|
198
142
|
|
|
199
|
-
|
|
143
|
+
**Response:**
|
|
200
144
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
Create a simple test to verify everything works:
|
|
214
|
-
|
|
215
|
-
**Option 1: Test with Firebase Token**
|
|
216
|
-
|
|
217
|
-
1. Get a Firebase ID token from your client app (or Firebase Console)
|
|
218
|
-
2. Send POST request to: `http://localhost:1337/api/firebase-authentication`
|
|
219
|
-
3. Body: `{ "idToken": "your-firebase-token-here" }`
|
|
220
|
-
4. Expected: `200 OK` with `{ user, jwt }` response
|
|
221
|
-
|
|
222
|
-
**Option 2: Test with Email/Password** (if configured)
|
|
223
|
-
|
|
224
|
-
1. Create a user in Firebase Console
|
|
225
|
-
2. Send POST to: `http://localhost:1337/api/firebase-authentication/emailLogin`
|
|
226
|
-
3. Body: `{ "email": "test@example.com", "password": "password123" }`
|
|
227
|
-
4. Expected: `200 OK` with `{ user, jwt }` response
|
|
228
|
-
|
|
229
|
-
**If tests fail:** Check [Troubleshooting](#troubleshooting) for common issues.
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
### Common Setup Mistakes
|
|
234
|
-
|
|
235
|
-
❌ **Encryption key too short** → Must be 32+ characters
|
|
236
|
-
❌ **Forgot to restart after uploading config** → Always restart Strapi
|
|
237
|
-
❌ **Wrong Firebase project** → Ensure service account matches your client app
|
|
238
|
-
❌ **Forgot to enable permissions** → Public role needs `authenticate` permission
|
|
239
|
-
❌ **Committed service account JSON to Git** → Use `.gitignore`
|
|
240
|
-
|
|
241
|
-
---
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"user": {
|
|
148
|
+
"id": 1,
|
|
149
|
+
"documentId": "abc123",
|
|
150
|
+
"email": "user@example.com",
|
|
151
|
+
"username": "user"
|
|
152
|
+
},
|
|
153
|
+
"jwt": "strapi-jwt-token"
|
|
154
|
+
}
|
|
155
|
+
```
|
|
242
156
|
|
|
243
|
-
|
|
157
|
+
## Client Integration
|
|
244
158
|
|
|
245
|
-
|
|
159
|
+
```javascript
|
|
160
|
+
import { getAuth } from "firebase/auth";
|
|
246
161
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
- Email templates for password reset
|
|
162
|
+
// After Firebase sign-in
|
|
163
|
+
const auth = getAuth();
|
|
164
|
+
const idToken = await auth.currentUser.getIdToken();
|
|
251
165
|
|
|
252
|
-
|
|
166
|
+
// Exchange for Strapi JWT
|
|
167
|
+
const response = await fetch("https://your-api.com/api/firebase-authentication", {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "Content-Type": "application/json" },
|
|
170
|
+
body: JSON.stringify({ idToken }),
|
|
171
|
+
});
|
|
253
172
|
|
|
254
|
-
|
|
173
|
+
const { user, jwt } = await response.json();
|
|
255
174
|
|
|
256
|
-
|
|
175
|
+
// Use JWT for Strapi API calls
|
|
176
|
+
const content = await fetch("https://your-api.com/api/articles", {
|
|
177
|
+
headers: { Authorization: `Bearer ${jwt}` },
|
|
178
|
+
});
|
|
179
|
+
```
|
|
257
180
|
|
|
258
181
|
## Configuration
|
|
259
182
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
**Minimal Configuration** (`config/plugins.js`):
|
|
183
|
+
### Plugin Config (`config/plugins.js`)
|
|
263
184
|
|
|
264
185
|
```javascript
|
|
265
186
|
module.exports = () => ({
|
|
266
187
|
"firebase-authentication": {
|
|
267
188
|
enabled: true,
|
|
268
189
|
config: {
|
|
190
|
+
// Required: Key used to encrypt Firebase credentials (min 32 characters)
|
|
269
191
|
FIREBASE_JSON_ENCRYPTION_KEY: process.env.FIREBASE_JSON_ENCRYPTION_KEY,
|
|
270
|
-
},
|
|
271
|
-
},
|
|
272
|
-
});
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
**Admin Panel Settings** (Settings → Firebase Authentication):
|
|
276
|
-
|
|
277
|
-
- Firebase Web API Key (for email/password login)
|
|
278
|
-
- Password requirements (regex + message)
|
|
279
|
-
- Password reset URL & email subject
|
|
280
|
-
- Magic link settings (enable, URL, subject, expiry)
|
|
281
|
-
- Phone-only user handling (`emailRequired: false` for phone-only apps)
|
|
282
|
-
|
|
283
|
-
## API Reference
|
|
284
|
-
|
|
285
|
-
### Public Endpoints
|
|
286
|
-
|
|
287
|
-
| Method | Endpoint | Purpose |
|
|
288
|
-
| ------ | ----------------------------------------------- | -------------------------------------------- |
|
|
289
|
-
| POST | `/api/firebase-authentication` | Exchange Firebase token for Strapi JWT |
|
|
290
|
-
| POST | `/api/firebase-authentication/emailLogin` | Email/password login (no SDK required) |
|
|
291
|
-
| POST | `/api/firebase-authentication/forgotPassword` | Request password reset email |
|
|
292
|
-
| POST | `/api/firebase-authentication/resetPassword` | Authenticated password change (requires JWT) |
|
|
293
|
-
| POST | `/api/firebase-authentication/requestMagicLink` | Request passwordless login email |
|
|
294
|
-
| GET | `/api/firebase-authentication/config` | Get public configuration |
|
|
295
|
-
|
|
296
|
-
### Password Reset Flow
|
|
297
|
-
|
|
298
|
-
There are two distinct password reset approaches in this plugin:
|
|
299
192
|
|
|
300
|
-
|
|
193
|
+
// Optional: Require email for all users (default: false)
|
|
194
|
+
// When false, phone-only users get auto-generated emails
|
|
195
|
+
emailRequired: false,
|
|
301
196
|
|
|
302
|
-
|
|
197
|
+
// Optional: Email pattern for phone-only users
|
|
198
|
+
// Tokens: {randomString}, {phoneNumber}, {timestamp}
|
|
199
|
+
emailPattern: "{randomString}@phone-user.firebase.local",
|
|
303
200
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
5. After success → Redirects to configured continue URL
|
|
309
|
-
6. User logs in normally with new password
|
|
310
|
-
|
|
311
|
-
**Configuration:** Set `passwordResetUrl` in Firebase Authentication settings (this is where users land AFTER resetting their password on Firebase's page).
|
|
312
|
-
|
|
313
|
-
#### 2. Authenticated Password Change
|
|
314
|
-
|
|
315
|
-
**For admin-initiated resets or users changing their own password:**
|
|
316
|
-
|
|
317
|
-
- **Endpoint:** `POST /api/firebase-authentication/resetPassword`
|
|
318
|
-
- **Requires:** Valid JWT in `Authorization` header + `{ "password": "newpassword" }` in body
|
|
319
|
-
- **Use cases:**
|
|
320
|
-
- Admin resetting a user's password via admin panel
|
|
321
|
-
- Authenticated user changing their own password
|
|
322
|
-
- **Returns:** Updated user object + fresh JWT for auto-login
|
|
323
|
-
|
|
324
|
-
**Note:** This endpoint is NOT part of the forgot password email flow. Use `forgotPassword` for email-based password reset.
|
|
325
|
-
|
|
326
|
-
### Admin Endpoints
|
|
327
|
-
|
|
328
|
-
Admin endpoints use the admin API type (no `/api` prefix) and require admin authentication.
|
|
329
|
-
|
|
330
|
-
**User Management:**
|
|
331
|
-
| Method | Endpoint | Purpose |
|
|
332
|
-
|--------|----------|---------|
|
|
333
|
-
| GET | `/firebase-authentication/users` | List/search users |
|
|
334
|
-
| POST | `/firebase-authentication/users` | Create user |
|
|
335
|
-
| GET | `/firebase-authentication/users/:id` | Get user |
|
|
336
|
-
| PUT | `/firebase-authentication/users/:id` | Update user |
|
|
337
|
-
| DELETE | `/firebase-authentication/users/:id` | Delete user |
|
|
338
|
-
| PUT | `/firebase-authentication/users/resetPassword/:id` | Reset password |
|
|
339
|
-
|
|
340
|
-
**Settings Management:**
|
|
341
|
-
| Method | Endpoint | Purpose |
|
|
342
|
-
|--------|----------|---------|
|
|
343
|
-
| GET | `/firebase-authentication/settings/firebase-config` | Get Firebase config |
|
|
344
|
-
| POST | `/firebase-authentication/settings/firebase-config` | Upload Firebase config |
|
|
345
|
-
| DELETE | `/firebase-authentication/settings/firebase-config` | Delete Firebase config |
|
|
346
|
-
| POST | `/firebase-authentication/settings/password-config` | Update password/magic link settings |
|
|
347
|
-
|
|
348
|
-
---
|
|
349
|
-
|
|
350
|
-
## Usage
|
|
351
|
-
|
|
352
|
-
**Basic Flow:**
|
|
353
|
-
|
|
354
|
-
1. User authenticates with Firebase Client SDK
|
|
355
|
-
2. Client gets Firebase ID token
|
|
356
|
-
3. Client sends token to Strapi: `POST /api/firebase-authentication`
|
|
357
|
-
4. Plugin returns Strapi JWT for API access
|
|
358
|
-
|
|
359
|
-
**Example (JavaScript):**
|
|
360
|
-
|
|
361
|
-
```javascript
|
|
362
|
-
// After Firebase authentication
|
|
363
|
-
const idToken = await firebaseUser.getIdToken();
|
|
364
|
-
|
|
365
|
-
// Exchange with Strapi
|
|
366
|
-
const response = await fetch("https://your-api.com/api/firebase-authentication", {
|
|
367
|
-
method: "POST",
|
|
368
|
-
headers: { "Content-Type": "application/json" },
|
|
369
|
-
body: JSON.stringify({ idToken }),
|
|
201
|
+
// Optional: Days to keep activity logs (default: null = forever)
|
|
202
|
+
activityLogRetentionDays: 90,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
370
205
|
});
|
|
371
|
-
|
|
372
|
-
const { user, jwt } = await response.json();
|
|
373
|
-
localStorage.setItem("jwt", jwt); // Use this JWT for Strapi API calls
|
|
374
206
|
```
|
|
375
207
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
208
|
+
### Environment Variables
|
|
209
|
+
|
|
210
|
+
| Variable | Required | Description |
|
|
211
|
+
| -------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
212
|
+
| `FIREBASE_JSON_ENCRYPTION_KEY` | Yes | AES encryption key for Firebase credentials. Minimum 32 characters. Generate with: `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"` |
|
|
213
|
+
| `FIREBASE_EMAIL_REQUIRED` | No | Set to `true` to require email for all users. Default: `false` |
|
|
214
|
+
| `FIREBASE_ACTIVITY_LOG_RETENTION_DAYS` | No | Auto-delete logs older than N days. Default: `null` (keep forever) |
|
|
215
|
+
|
|
216
|
+
### Admin Panel Settings
|
|
217
|
+
|
|
218
|
+
Configure in **Settings → Firebase Authentication**:
|
|
219
|
+
|
|
220
|
+
**General**
|
|
221
|
+
| Setting | Default | Description |
|
|
222
|
+
|---------|---------|-------------|
|
|
223
|
+
| Firebase Web API Key | - | Required for `emailLogin` endpoint. Get from Firebase Console → Project Settings → General |
|
|
224
|
+
|
|
225
|
+
**Password Settings**
|
|
226
|
+
| Setting | Default | Description |
|
|
227
|
+
|---------|---------|-------------|
|
|
228
|
+
| Password Requirements Regex | `^.{6,}$` | Regex pattern for password validation (default: 6+ chars) |
|
|
229
|
+
| Password Requirements Message | "Password must be at least 6 characters long" | Error message shown when password doesn't match regex |
|
|
230
|
+
| Password Reset URL | `http://localhost:3000/reset-password` | URL where users land after resetting password |
|
|
231
|
+
| Password Reset Email Subject | "Reset Your Password" | Subject line for password reset emails |
|
|
232
|
+
| Include Credentials in Reset Link | `false` | Include Firebase custom token for auto-login after reset |
|
|
233
|
+
|
|
234
|
+
**Magic Link (Passwordless)**
|
|
235
|
+
| Setting | Default | Description |
|
|
236
|
+
|---------|---------|-------------|
|
|
237
|
+
| Enable Magic Link | `false` | Toggle passwordless email authentication |
|
|
238
|
+
| Magic Link URL | `http://localhost:1338/verify-magic-link.html` | Landing page for magic link clicks |
|
|
239
|
+
| Magic Link Email Subject | "Sign in to Your Application" | Subject line for magic link emails |
|
|
240
|
+
| Magic Link Expiry Hours | `1` | Token validity (1-72 hours) |
|
|
241
|
+
|
|
242
|
+
**Email Verification**
|
|
243
|
+
| Setting | Default | Description |
|
|
244
|
+
|---------|---------|-------------|
|
|
245
|
+
| Email Verification URL | `http://localhost:3000/verify-email` | URL for email verification redirect |
|
|
246
|
+
| Email Verification Subject | "Verify Your Email" | Subject line for verification emails |
|
|
247
|
+
| Include Credentials in Verification Link | `false` | Include Firebase custom token for auto-login after verification |
|
|
248
|
+
|
|
249
|
+
### Firebase Service Account
|
|
250
|
+
|
|
251
|
+
The service account JSON (uploaded via admin panel) should contain:
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"type": "service_account",
|
|
256
|
+
"project_id": "your-project-id",
|
|
257
|
+
"private_key_id": "...",
|
|
258
|
+
"private_key": "-----BEGIN PRIVATE KEY-----\n...",
|
|
259
|
+
"client_email": "firebase-adminsdk-xxxxx@your-project.iam.gserviceaccount.com",
|
|
260
|
+
"client_id": "...",
|
|
261
|
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
|
262
|
+
"token_uri": "https://oauth2.googleapis.com/token"
|
|
263
|
+
}
|
|
264
|
+
```
|
|
383
265
|
|
|
384
|
-
|
|
266
|
+
Get this from: [Firebase Console](https://console.firebase.google.com/) → Project Settings → Service Accounts → Generate New Private Key
|
|
385
267
|
|
|
386
|
-
|
|
268
|
+
## Admin Panel
|
|
387
269
|
|
|
388
|
-
**
|
|
270
|
+
Access at **Plugins → Firebase Authentication**:
|
|
389
271
|
|
|
390
|
-
-
|
|
391
|
-
-
|
|
392
|
-
-
|
|
393
|
-
-
|
|
272
|
+
- View and search Firebase users
|
|
273
|
+
- Edit user details
|
|
274
|
+
- Delete users (from Firebase, Strapi, or both)
|
|
275
|
+
- Send password reset emails
|
|
276
|
+
- View activity logs
|
|
394
277
|
|
|
395
278
|
## Troubleshooting
|
|
396
279
|
|
|
397
|
-
###
|
|
398
|
-
|
|
399
|
-
**Solution:**
|
|
280
|
+
### "Firebase is not initialized"
|
|
400
281
|
|
|
401
|
-
1.
|
|
402
|
-
2. Upload Firebase service account JSON
|
|
403
|
-
3. Restart Strapi
|
|
404
|
-
4. Check
|
|
282
|
+
1. Check `FIREBASE_JSON_ENCRYPTION_KEY` is set (minimum 32 characters)
|
|
283
|
+
2. Upload Firebase service account JSON via admin panel
|
|
284
|
+
3. Restart Strapi after uploading config
|
|
285
|
+
4. Check console for initialization errors
|
|
405
286
|
|
|
406
|
-
|
|
287
|
+
### "Token validation failed"
|
|
407
288
|
|
|
408
|
-
|
|
289
|
+
1. Token expired (1 hour TTL) - get a fresh token from client
|
|
290
|
+
2. Wrong Firebase project - ensure service account matches your app
|
|
291
|
+
3. Check Firebase Console for service status
|
|
409
292
|
|
|
410
|
-
|
|
293
|
+
### "Emails not sending"
|
|
411
294
|
|
|
412
|
-
|
|
413
|
-
2. Verify client and server use the same Firebase project
|
|
414
|
-
3. Confirm service account JSON matches your Firebase project ID
|
|
415
|
-
4. Check Firebase Console for service status
|
|
416
|
-
|
|
417
|
-
---
|
|
418
|
-
|
|
419
|
-
### 🔴 Email Not Sending
|
|
420
|
-
|
|
421
|
-
**Solution:**
|
|
422
|
-
|
|
423
|
-
Install and configure Strapi Email Plugin:
|
|
295
|
+
Install and configure Strapi email provider:
|
|
424
296
|
|
|
425
297
|
```bash
|
|
426
298
|
yarn add @strapi/provider-email-sendgrid
|
|
@@ -428,128 +300,24 @@ yarn add @strapi/provider-email-sendgrid
|
|
|
428
300
|
|
|
429
301
|
```javascript
|
|
430
302
|
// config/plugins.js
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
defaultFrom:
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
303
|
+
module.exports = () => ({
|
|
304
|
+
email: {
|
|
305
|
+
config: {
|
|
306
|
+
provider: "sendgrid",
|
|
307
|
+
providerOptions: { apiKey: process.env.SENDGRID_API_KEY },
|
|
308
|
+
settings: { defaultFrom: "noreply@yourapp.com" },
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
// ... firebase-authentication config
|
|
312
|
+
});
|
|
440
313
|
```
|
|
441
314
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
---
|
|
445
|
-
|
|
446
|
-
**Need more help?** Check [Firebase Console](https://console.firebase.google.com/) logs or [GitHub Issues](https://github.com/meta-cto/strapi-plugin-firebase-auth/issues)
|
|
447
|
-
|
|
448
|
-
## Best Practices
|
|
449
|
-
|
|
450
|
-
- Use Firebase SDK for authentication (not `emailLogin` for production)
|
|
451
|
-
- Store JWTs in httpOnly cookies (production) or secure storage (mobile)
|
|
452
|
-
- Configure Strapi Email Plugin (SendGrid, Mailgun, SES) for production
|
|
453
|
-
- Implement rate limiting on public endpoints
|
|
454
|
-
- Enforce HTTPS for password reset URLs
|
|
455
|
-
- Monitor Firebase quotas regularly
|
|
456
|
-
- Keep dependencies updated
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
## Support
|
|
461
|
-
|
|
462
|
-
### Questions and Issues
|
|
463
|
-
|
|
464
|
-
If you encounter problems or have questions:
|
|
465
|
-
|
|
466
|
-
1. **Check Troubleshooting Section:** Review common errors above
|
|
467
|
-
2. **Firebase Documentation:** [firebase.google.com/docs/auth](https://firebase.google.com/docs/auth)
|
|
468
|
-
3. **Strapi Documentation:** [docs.strapi.io](https://docs.strapi.io)
|
|
469
|
-
4. **GitHub Issues:** [github.com/meta-cto/strapi-plugin-firebase-auth/issues](https://github.com/meta-cto/strapi-plugin-firebase-auth/issues)
|
|
470
|
-
- Search existing issues first
|
|
471
|
-
- Provide detailed information when creating new issues
|
|
315
|
+
## Links
|
|
472
316
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
1. **Plugin version:** Check `package.json`
|
|
478
|
-
2. **Strapi version:** Run `yarn strapi version`
|
|
479
|
-
3. **Node version:** Run `node --version`
|
|
480
|
-
4. **Error message:** Full error text and stack trace
|
|
481
|
-
5. **Steps to reproduce:** Detailed steps to trigger the issue
|
|
482
|
-
6. **Configuration:** Relevant plugin configuration (redact sensitive data)
|
|
483
|
-
7. **Expected behavior:** What should happen
|
|
484
|
-
8. **Actual behavior:** What actually happens
|
|
485
|
-
|
|
486
|
-
### Feature Requests
|
|
487
|
-
|
|
488
|
-
To request new features:
|
|
489
|
-
|
|
490
|
-
1. Search existing feature requests
|
|
491
|
-
2. Create detailed proposal with use case
|
|
492
|
-
3. Explain why feature would be beneficial
|
|
493
|
-
4. Suggest implementation approach (if applicable)
|
|
494
|
-
|
|
495
|
-
### Community
|
|
496
|
-
|
|
497
|
-
- **GitHub Discussions:** Ask questions and share experiences
|
|
498
|
-
- **Discord:** Join Strapi community Discord server
|
|
499
|
-
- **Stack Overflow:** Tag questions with `strapi` and `firebase`
|
|
500
|
-
|
|
501
|
-
---
|
|
317
|
+
- [GitHub Issues](https://github.com/meta-cto/strapi-plugin-firebase-auth/issues)
|
|
318
|
+
- [Firebase Auth Docs](https://firebase.google.com/docs/auth)
|
|
319
|
+
- [Strapi v5 Docs](https://docs.strapi.io)
|
|
502
320
|
|
|
503
321
|
## License
|
|
504
322
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
---
|
|
508
|
-
|
|
509
|
-
## Changelog
|
|
510
|
-
|
|
511
|
-
See `CHANGELOG.md` for version history and release notes.
|
|
512
|
-
|
|
513
|
-
---
|
|
514
|
-
|
|
515
|
-
## Credits
|
|
516
|
-
|
|
517
|
-
Developed and maintained by **Meta CTO** team.
|
|
518
|
-
|
|
519
|
-
**Contributors:**
|
|
520
|
-
|
|
521
|
-
- Firebase Admin SDK: Google
|
|
522
|
-
- Strapi Framework: Strapi Solutions SAS
|
|
523
|
-
- AES Encryption: crypto-js library
|
|
524
|
-
|
|
525
|
-
---
|
|
526
|
-
|
|
527
|
-
## Additional Resources
|
|
528
|
-
|
|
529
|
-
**Firebase Documentation:**
|
|
530
|
-
|
|
531
|
-
- [Firebase Authentication](https://firebase.google.com/docs/auth)
|
|
532
|
-
- [Firebase Admin SDK](https://firebase.google.com/docs/admin/setup)
|
|
533
|
-
- Platform Guides: [Web](https://firebase.google.com/docs/web/setup) | [iOS](https://firebase.google.com/docs/ios/setup) | [Android](https://firebase.google.com/docs/android/setup)
|
|
534
|
-
|
|
535
|
-
**Strapi Documentation:**
|
|
536
|
-
|
|
537
|
-
- [Strapi v5](https://docs.strapi.io/dev-docs/intro)
|
|
538
|
-
- [Email Providers](https://market.strapi.io/providers) (SendGrid, Mailgun, Amazon SES)
|
|
539
|
-
|
|
540
|
-
**Firebase Extensions:**
|
|
541
|
-
|
|
542
|
-
- [Trigger Email Extension](https://extensions.dev/extensions/firebase/firestore-send-email)
|
|
543
|
-
|
|
544
|
-
---
|
|
545
|
-
|
|
546
|
-
**Thank you for using Strapi Plugin Firebase Authentication!** 🎉
|
|
547
|
-
|
|
548
|
-
If you find this plugin helpful, please consider:
|
|
549
|
-
|
|
550
|
-
- Starring the GitHub repository
|
|
551
|
-
- Sharing with your community
|
|
552
|
-
- Contributing improvements
|
|
553
|
-
- Reporting issues to help us improve
|
|
554
|
-
|
|
555
|
-
Happy coding! 🚀
|
|
323
|
+
MIT License - see [LICENSE.md](LICENSE.md)
|
|
@@ -5,9 +5,9 @@ const admin = require("@strapi/strapi/admin");
|
|
|
5
5
|
const reactRouterDom = require("react-router-dom");
|
|
6
6
|
const rt = require("@radix-ui/react-tooltip");
|
|
7
7
|
const m = require("react");
|
|
8
|
-
const api = require("./api-
|
|
8
|
+
const api = require("./api-C0GYp4ji.js");
|
|
9
9
|
const reactIntl = require("react-intl");
|
|
10
|
-
const index = require("./index-
|
|
10
|
+
const index = require("./index-BEmqy-R3.js");
|
|
11
11
|
const styled = require("styled-components");
|
|
12
12
|
const rx = require("react-icons/rx");
|
|
13
13
|
const ai = require("react-icons/ai");
|
|
@@ -3,9 +3,9 @@ import { Layouts, useQueryParams as useQueryParams$1, getFetchClient, Pagination
|
|
|
3
3
|
import { useNavigate, useLocation, useParams, Routes, Route } from "react-router-dom";
|
|
4
4
|
import { Provider } from "@radix-ui/react-tooltip";
|
|
5
5
|
import m__default, { useState, useCallback, useMemo, useEffect, useRef, useLayoutEffect } from "react";
|
|
6
|
-
import { W as Wc, T, R, z as zn, A as Ar, k as k1, a as A1, b as R1, c as Tr, I, n as n1, C as C1, $ as $1, d as T1, y as yo, w as wo, e as d0, f as c0, o as ot, _ as _m, S as S1, X as X0, g as Cm, h as getFirebaseConfig$1, H as Hm, E as E1, P as Ps, i as o1, s as s1, j as a1, l as l1, m as bl } from "./api-
|
|
6
|
+
import { W as Wc, T, R, z as zn, A as Ar, k as k1, a as A1, b as R1, c as Tr, I, n as n1, C as C1, $ as $1, d as T1, y as yo, w as wo, e as d0, f as c0, o as ot, _ as _m, S as S1, X as X0, g as Cm, h as getFirebaseConfig$1, H as Hm, E as E1, P as Ps, i as o1, s as s1, j as a1, l as l1, m as bl } from "./api-BXpBvqeN.mjs";
|
|
7
7
|
import { useIntl } from "react-intl";
|
|
8
|
-
import { i as isArguments_1, a as isBufferExports, b as isTypedArray_1, c as isLength_1, d as isFunction_1, _ as _Stack, e as _getTag, f as _equalArrays, g as _equalByTag, h as isObjectLike_1, j as getDefaultExportFromCjs, U as U2, k as _baseGetTag, l as _MapCache, m as _Symbol, n as m3, o as bn, N as Nn, Y as Y2, J as J2, P as PLUGIN_ID, p as getAugmentedNamespace, q as commonjsGlobal, u as un, s as sn, r as c5, w as w5, t as _3 } from "./index-
|
|
8
|
+
import { i as isArguments_1, a as isBufferExports, b as isTypedArray_1, c as isLength_1, d as isFunction_1, _ as _Stack, e as _getTag, f as _equalArrays, g as _equalByTag, h as isObjectLike_1, j as getDefaultExportFromCjs, U as U2, k as _baseGetTag, l as _MapCache, m as _Symbol, n as m3, o as bn, N as Nn, Y as Y2, J as J2, P as PLUGIN_ID, p as getAugmentedNamespace, q as commonjsGlobal, u as un, s as sn, r as c5, w as w5, t as _3 } from "./index-K_RiV2x9.mjs";
|
|
9
9
|
import styled from "styled-components";
|
|
10
10
|
import { RxCheck, RxCross2 } from "react-icons/rx";
|
|
11
11
|
import { AiOutlineUserAdd, AiFillPhone, AiFillMail, AiFillYahoo, AiFillGithub, AiFillTwitterCircle, AiFillFacebook, AiFillApple, AiFillGoogleCircle } from "react-icons/ai";
|
|
@@ -5,7 +5,7 @@ import { jsxs, Fragment as Fragment$1, jsx } from "react/jsx-runtime";
|
|
|
5
5
|
import * as rt from "@radix-ui/react-tooltip";
|
|
6
6
|
import * as we$1 from "react-dom";
|
|
7
7
|
import we__default, { flushSync, createPortal } from "react-dom";
|
|
8
|
-
import { q as commonjsGlobal, J as J2, R as R3, C as C5, v as f5, x as h5, w as w5, y as a5, N as Nn$1, z as r3, A as f3, u as un$1, K as K2, B as o5, P as PLUGIN_ID } from "./index-
|
|
8
|
+
import { q as commonjsGlobal, J as J2, R as R3, C as C5, v as f5, x as h5, w as w5, y as a5, N as Nn$1, z as r3, A as f3, u as un$1, K as K2, B as o5, P as PLUGIN_ID } from "./index-K_RiV2x9.mjs";
|
|
9
9
|
import { getFetchClient } from "@strapi/strapi/admin";
|
|
10
10
|
function $b1b2314f5f9a1d84$export$25bec8c6f54ee79a(callback) {
|
|
11
11
|
const callbackRef = useRef(callback);
|
|
@@ -4,7 +4,7 @@ const m = require("react");
|
|
|
4
4
|
const jsxRuntime = require("react/jsx-runtime");
|
|
5
5
|
const rt = require("@radix-ui/react-tooltip");
|
|
6
6
|
const we$1 = require("react-dom");
|
|
7
|
-
const index$2 = require("./index-
|
|
7
|
+
const index$2 = require("./index-BEmqy-R3.js");
|
|
8
8
|
const admin = require("@strapi/strapi/admin");
|
|
9
9
|
function _interopNamespace(e) {
|
|
10
10
|
if (e && e.__esModule) return e;
|
|
@@ -2661,7 +2661,7 @@ const index = {
|
|
|
2661
2661
|
id: `${PLUGIN_ID}.page.title`,
|
|
2662
2662
|
defaultMessage: PLUGIN_ID
|
|
2663
2663
|
},
|
|
2664
|
-
Component: () => Promise.resolve().then(() => require("./App-
|
|
2664
|
+
Component: () => Promise.resolve().then(() => require("./App-CSFciBSN.js")).then((mod) => ({
|
|
2665
2665
|
default: mod.App
|
|
2666
2666
|
})),
|
|
2667
2667
|
permissions: PERMISSIONS["menu-link"]
|
|
@@ -2683,7 +2683,7 @@ const index = {
|
|
|
2683
2683
|
id: "settings",
|
|
2684
2684
|
to: `/settings/${PLUGIN_ID}`,
|
|
2685
2685
|
async Component() {
|
|
2686
|
-
const component = await Promise.resolve().then(() => require("./index-
|
|
2686
|
+
const component = await Promise.resolve().then(() => require("./index-CfYs8WkU.js"));
|
|
2687
2687
|
return component.default;
|
|
2688
2688
|
},
|
|
2689
2689
|
permissions: PERMISSIONS["menu-link"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect } from "react";
|
|
3
|
-
import { T, R, I, Z as Zm, z as zn, X as X0, P as Ps, O as O1, E as E1, r as r1, n as n1, h as getFirebaseConfig, p as saveFirebaseConfig, q as delFirebaseConfig, t as savePasswordSettings } from "./api-
|
|
3
|
+
import { T, R, I, Z as Zm, z as zn, X as X0, P as Ps, O as O1, E as E1, r as r1, n as n1, h as getFirebaseConfig, p as saveFirebaseConfig, q as delFirebaseConfig, t as savePasswordSettings } from "./api-BXpBvqeN.mjs";
|
|
4
4
|
import { useNotification, Page } from "@strapi/strapi/admin";
|
|
5
5
|
import { useNavigate } from "react-router-dom";
|
|
6
6
|
function SettingsPage() {
|
|
@@ -356,7 +356,7 @@ function SettingsPage() {
|
|
|
356
356
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
357
357
|
/* @__PURE__ */ jsx(T, { style: { padding: 32 }, direction: "column", alignItems: "flex-start", gap: 4, children: /* @__PURE__ */ jsxs(R, { style: { width: "100%" }, children: [
|
|
358
358
|
/* @__PURE__ */ jsxs(R, { marginBottom: 6, padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", children: [
|
|
359
|
-
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Firebase Authentication" }),
|
|
359
|
+
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Firebase Authentication" }),
|
|
360
360
|
/* @__PURE__ */ jsx(
|
|
361
361
|
I,
|
|
362
362
|
{
|
|
@@ -564,39 +564,45 @@ function SettingsPage() {
|
|
|
564
564
|
] })
|
|
565
565
|
] }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(R, { padding: 4, background: "neutral0", children: [
|
|
566
566
|
/* @__PURE__ */ jsxs(R, { marginBottom: 4, children: [
|
|
567
|
-
/* @__PURE__ */ jsx(I, { variant: "
|
|
567
|
+
/* @__PURE__ */ jsx(I, { variant: "beta", fontWeight: "bold", style: { marginBottom: "8px" }, children: "Service Account Configuration" }),
|
|
568
568
|
/* @__PURE__ */ jsx(R, { marginBottom: 3, children: /* @__PURE__ */ jsxs(I, { variant: "pi", textColor: "neutral600", component: "span", children: [
|
|
569
569
|
/* @__PURE__ */ jsx("strong", { children: "Required" }),
|
|
570
570
|
" - Enables Firebase Admin SDK for server-side authentication"
|
|
571
571
|
] }) }),
|
|
572
572
|
/* @__PURE__ */ jsxs(T, { gap: 2, alignItems: "center", justifyContent: "space-between", children: [
|
|
573
573
|
/* @__PURE__ */ jsxs(T, { gap: 2, alignItems: "center", children: [
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
574
|
+
firebaseJsonValue?.firebaseConfigJson && (() => {
|
|
575
|
+
try {
|
|
576
|
+
const config = JSON.parse(firebaseJsonValue.firebaseConfigJson);
|
|
577
|
+
const projectId = config.project_id || config.projectId || "Unknown Project";
|
|
578
|
+
const keyId = config.private_key_id || "N/A";
|
|
579
|
+
return /* @__PURE__ */ jsxs(I, { variant: "omega", textColor: "neutral600", children: [
|
|
580
|
+
"Project: ",
|
|
581
|
+
projectId,
|
|
582
|
+
" | Key: ",
|
|
583
|
+
keyId
|
|
584
|
+
] });
|
|
585
|
+
} catch (e) {
|
|
586
|
+
return /* @__PURE__ */ jsx(I, { variant: "omega", textColor: "neutral600", children: "Invalid Config" });
|
|
587
|
+
}
|
|
588
|
+
})(),
|
|
586
589
|
/* @__PURE__ */ jsx(Ps, { backgroundColor: "success200", textColor: "success700", size: "S", children: "✓ CONFIGURED" })
|
|
587
590
|
] }),
|
|
588
591
|
/* @__PURE__ */ jsx(zn, { variant: "danger-light", size: "S", onClick: handleDeleteFirebaseJsonConfig, children: "Delete Config" })
|
|
589
592
|
] })
|
|
590
593
|
] }),
|
|
591
594
|
/* @__PURE__ */ jsxs(R, { paddingTop: 4, style: { borderTop: "1px solid #eaeaef" }, children: [
|
|
592
|
-
/* @__PURE__ */ jsx(I, { variant: "
|
|
595
|
+
/* @__PURE__ */ jsx(I, { variant: "beta", fontWeight: "bold", style: { marginBottom: "8px" }, children: "Web API Key Configuration" }),
|
|
593
596
|
/* @__PURE__ */ jsx(R, { marginBottom: 3, children: /* @__PURE__ */ jsxs(I, { variant: "pi", textColor: "neutral600", component: "span", children: [
|
|
594
597
|
/* @__PURE__ */ jsx("strong", { children: "Optional" }),
|
|
595
598
|
" - Only needed for email/password login via emailLogin endpoint"
|
|
596
599
|
] }) }),
|
|
597
600
|
/* @__PURE__ */ jsxs(T, { gap: 2, alignItems: "center", justifyContent: "space-between", children: [
|
|
598
601
|
/* @__PURE__ */ jsxs(T, { gap: 2, alignItems: "center", children: [
|
|
599
|
-
firebaseWebApiKey?.trim() && /* @__PURE__ */
|
|
602
|
+
firebaseWebApiKey?.trim() && /* @__PURE__ */ jsxs(I, { variant: "omega", textColor: "neutral600", children: [
|
|
603
|
+
"Key: ",
|
|
604
|
+
firebaseWebApiKey
|
|
605
|
+
] }),
|
|
600
606
|
firebaseWebApiKey?.trim() ? /* @__PURE__ */ jsx(Ps, { backgroundColor: "success200", textColor: "success700", size: "S", children: "✓ CONFIGURED" }) : /* @__PURE__ */ jsx(Ps, { backgroundColor: "neutral200", textColor: "neutral700", size: "S", children: "NOT SET" })
|
|
601
607
|
] }),
|
|
602
608
|
firebaseWebApiKey?.trim() ? /* @__PURE__ */ jsx(zn, { variant: "danger-light", size: "S", onClick: handleRemoveWebApiKey, children: "Delete Config" }) : /* @__PURE__ */ jsx(zn, { variant: "secondary", size: "S", onClick: handleAddWebApiKey, children: "+ Add Web API Key" })
|
|
@@ -606,7 +612,7 @@ function SettingsPage() {
|
|
|
606
612
|
})()
|
|
607
613
|
] }),
|
|
608
614
|
/* @__PURE__ */ jsxs(R, { padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", marginBottom: 6, children: [
|
|
609
|
-
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Password Reset Settings" }),
|
|
615
|
+
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Password Reset Settings" }),
|
|
610
616
|
/* @__PURE__ */ jsx(
|
|
611
617
|
I,
|
|
612
618
|
{
|
|
@@ -729,7 +735,7 @@ function SettingsPage() {
|
|
|
729
735
|
)
|
|
730
736
|
] }),
|
|
731
737
|
/* @__PURE__ */ jsxs(R, { padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", marginBottom: 6, children: [
|
|
732
|
-
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Email Verification" }),
|
|
738
|
+
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Email Verification" }),
|
|
733
739
|
/* @__PURE__ */ jsx(
|
|
734
740
|
I,
|
|
735
741
|
{
|
|
@@ -802,7 +808,7 @@ function SettingsPage() {
|
|
|
802
808
|
)
|
|
803
809
|
] }),
|
|
804
810
|
/* @__PURE__ */ jsxs(R, { padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", marginBottom: 6, children: [
|
|
805
|
-
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Magic Link Authentication" }),
|
|
811
|
+
/* @__PURE__ */ jsx(I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Magic Link Authentication" }),
|
|
806
812
|
/* @__PURE__ */ jsx(
|
|
807
813
|
I,
|
|
808
814
|
{
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const m = require("react");
|
|
5
|
-
const api = require("./api-
|
|
5
|
+
const api = require("./api-C0GYp4ji.js");
|
|
6
6
|
const admin = require("@strapi/strapi/admin");
|
|
7
7
|
const reactRouterDom = require("react-router-dom");
|
|
8
8
|
function SettingsPage() {
|
|
@@ -358,7 +358,7 @@ function SettingsPage() {
|
|
|
358
358
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
359
359
|
/* @__PURE__ */ jsxRuntime.jsx(api.T, { style: { padding: 32 }, direction: "column", alignItems: "flex-start", gap: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(api.R, { style: { width: "100%" }, children: [
|
|
360
360
|
/* @__PURE__ */ jsxRuntime.jsxs(api.R, { marginBottom: 6, padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", children: [
|
|
361
|
-
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Firebase Authentication" }),
|
|
361
|
+
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Firebase Authentication" }),
|
|
362
362
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
363
363
|
api.I,
|
|
364
364
|
{
|
|
@@ -566,39 +566,45 @@ function SettingsPage() {
|
|
|
566
566
|
] })
|
|
567
567
|
] }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(api.R, { padding: 4, background: "neutral0", children: [
|
|
568
568
|
/* @__PURE__ */ jsxRuntime.jsxs(api.R, { marginBottom: 4, children: [
|
|
569
|
-
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "
|
|
569
|
+
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "beta", fontWeight: "bold", style: { marginBottom: "8px" }, children: "Service Account Configuration" }),
|
|
570
570
|
/* @__PURE__ */ jsxRuntime.jsx(api.R, { marginBottom: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(api.I, { variant: "pi", textColor: "neutral600", component: "span", children: [
|
|
571
571
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Required" }),
|
|
572
572
|
" - Enables Firebase Admin SDK for server-side authentication"
|
|
573
573
|
] }) }),
|
|
574
574
|
/* @__PURE__ */ jsxRuntime.jsxs(api.T, { gap: 2, alignItems: "center", justifyContent: "space-between", children: [
|
|
575
575
|
/* @__PURE__ */ jsxRuntime.jsxs(api.T, { gap: 2, alignItems: "center", children: [
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
576
|
+
firebaseJsonValue?.firebaseConfigJson && (() => {
|
|
577
|
+
try {
|
|
578
|
+
const config = JSON.parse(firebaseJsonValue.firebaseConfigJson);
|
|
579
|
+
const projectId = config.project_id || config.projectId || "Unknown Project";
|
|
580
|
+
const keyId = config.private_key_id || "N/A";
|
|
581
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(api.I, { variant: "omega", textColor: "neutral600", children: [
|
|
582
|
+
"Project: ",
|
|
583
|
+
projectId,
|
|
584
|
+
" | Key: ",
|
|
585
|
+
keyId
|
|
586
|
+
] });
|
|
587
|
+
} catch (e) {
|
|
588
|
+
return /* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "omega", textColor: "neutral600", children: "Invalid Config" });
|
|
589
|
+
}
|
|
590
|
+
})(),
|
|
588
591
|
/* @__PURE__ */ jsxRuntime.jsx(api.Ps, { backgroundColor: "success200", textColor: "success700", size: "S", children: "✓ CONFIGURED" })
|
|
589
592
|
] }),
|
|
590
593
|
/* @__PURE__ */ jsxRuntime.jsx(api.zn, { variant: "danger-light", size: "S", onClick: handleDeleteFirebaseJsonConfig, children: "Delete Config" })
|
|
591
594
|
] })
|
|
592
595
|
] }),
|
|
593
596
|
/* @__PURE__ */ jsxRuntime.jsxs(api.R, { paddingTop: 4, style: { borderTop: "1px solid #eaeaef" }, children: [
|
|
594
|
-
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "
|
|
597
|
+
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "beta", fontWeight: "bold", style: { marginBottom: "8px" }, children: "Web API Key Configuration" }),
|
|
595
598
|
/* @__PURE__ */ jsxRuntime.jsx(api.R, { marginBottom: 3, children: /* @__PURE__ */ jsxRuntime.jsxs(api.I, { variant: "pi", textColor: "neutral600", component: "span", children: [
|
|
596
599
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Optional" }),
|
|
597
600
|
" - Only needed for email/password login via emailLogin endpoint"
|
|
598
601
|
] }) }),
|
|
599
602
|
/* @__PURE__ */ jsxRuntime.jsxs(api.T, { gap: 2, alignItems: "center", justifyContent: "space-between", children: [
|
|
600
603
|
/* @__PURE__ */ jsxRuntime.jsxs(api.T, { gap: 2, alignItems: "center", children: [
|
|
601
|
-
firebaseWebApiKey?.trim() && /* @__PURE__ */ jsxRuntime.
|
|
604
|
+
firebaseWebApiKey?.trim() && /* @__PURE__ */ jsxRuntime.jsxs(api.I, { variant: "omega", textColor: "neutral600", children: [
|
|
605
|
+
"Key: ",
|
|
606
|
+
firebaseWebApiKey
|
|
607
|
+
] }),
|
|
602
608
|
firebaseWebApiKey?.trim() ? /* @__PURE__ */ jsxRuntime.jsx(api.Ps, { backgroundColor: "success200", textColor: "success700", size: "S", children: "✓ CONFIGURED" }) : /* @__PURE__ */ jsxRuntime.jsx(api.Ps, { backgroundColor: "neutral200", textColor: "neutral700", size: "S", children: "NOT SET" })
|
|
603
609
|
] }),
|
|
604
610
|
firebaseWebApiKey?.trim() ? /* @__PURE__ */ jsxRuntime.jsx(api.zn, { variant: "danger-light", size: "S", onClick: handleRemoveWebApiKey, children: "Delete Config" }) : /* @__PURE__ */ jsxRuntime.jsx(api.zn, { variant: "secondary", size: "S", onClick: handleAddWebApiKey, children: "+ Add Web API Key" })
|
|
@@ -608,7 +614,7 @@ function SettingsPage() {
|
|
|
608
614
|
})()
|
|
609
615
|
] }),
|
|
610
616
|
/* @__PURE__ */ jsxRuntime.jsxs(api.R, { padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", marginBottom: 6, children: [
|
|
611
|
-
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Password Reset Settings" }),
|
|
617
|
+
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Password Reset Settings" }),
|
|
612
618
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
613
619
|
api.I,
|
|
614
620
|
{
|
|
@@ -731,7 +737,7 @@ function SettingsPage() {
|
|
|
731
737
|
)
|
|
732
738
|
] }),
|
|
733
739
|
/* @__PURE__ */ jsxRuntime.jsxs(api.R, { padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", marginBottom: 6, children: [
|
|
734
|
-
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Email Verification" }),
|
|
740
|
+
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Email Verification" }),
|
|
735
741
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
736
742
|
api.I,
|
|
737
743
|
{
|
|
@@ -804,7 +810,7 @@ function SettingsPage() {
|
|
|
804
810
|
)
|
|
805
811
|
] }),
|
|
806
812
|
/* @__PURE__ */ jsxRuntime.jsxs(api.R, { padding: 4, background: "neutral0", borderRadius: "4px", shadow: "filterShadow", marginBottom: 6, children: [
|
|
807
|
-
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px" }, children: "Magic Link Authentication" }),
|
|
813
|
+
/* @__PURE__ */ jsxRuntime.jsx(api.I, { variant: "alpha", as: "h2", style: { display: "block", marginBottom: "8px", fontSize: "2.4rem", fontWeight: 600 }, children: "Magic Link Authentication" }),
|
|
808
814
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
809
815
|
api.I,
|
|
810
816
|
{
|
|
@@ -2660,7 +2660,7 @@ const index = {
|
|
|
2660
2660
|
id: `${PLUGIN_ID}.page.title`,
|
|
2661
2661
|
defaultMessage: PLUGIN_ID
|
|
2662
2662
|
},
|
|
2663
|
-
Component: () => import("./App-
|
|
2663
|
+
Component: () => import("./App-Dzl5W6YR.mjs").then((mod) => ({
|
|
2664
2664
|
default: mod.App
|
|
2665
2665
|
})),
|
|
2666
2666
|
permissions: PERMISSIONS["menu-link"]
|
|
@@ -2682,7 +2682,7 @@ const index = {
|
|
|
2682
2682
|
id: "settings",
|
|
2683
2683
|
to: `/settings/${PLUGIN_ID}`,
|
|
2684
2684
|
async Component() {
|
|
2685
|
-
const component = await import("./index-
|
|
2685
|
+
const component = await import("./index-CCa5Fl4r.mjs");
|
|
2686
2686
|
return component.default;
|
|
2687
2687
|
},
|
|
2688
2688
|
permissions: PERMISSIONS["menu-link"]
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -393,9 +393,6 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
393
393
|
} catch (error) {
|
|
394
394
|
strapi2.log.warn(`[Firebase Auth] Migration warning: ${error.message}`);
|
|
395
395
|
}
|
|
396
|
-
if (process.env.FIREBASE_REPORT_ORPHANS === "true") {
|
|
397
|
-
await reportOrphanUsers(strapi2);
|
|
398
|
-
}
|
|
399
396
|
if (process.env.RUN_FIREBASE_MIGRATION === "true") {
|
|
400
397
|
const dryRun = process.env.DRY_RUN === "true";
|
|
401
398
|
strapi2.log.info("");
|
|
@@ -407,6 +404,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
407
404
|
try {
|
|
408
405
|
strapi2.log.info("[Firebase Auth] Auto-link enabled via FIREBASE_AUTO_LINK_ON_STARTUP");
|
|
409
406
|
await strapi2.plugin("firebase-authentication").service("autoLinkService").linkAllUsers(strapi2);
|
|
407
|
+
await reportOrphanUsers(strapi2);
|
|
410
408
|
} catch (error) {
|
|
411
409
|
strapi2.log.error(`Auto-linking failed: ${error.message}`);
|
|
412
410
|
}
|
package/dist/server/index.mjs
CHANGED
|
@@ -366,9 +366,6 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
366
366
|
} catch (error) {
|
|
367
367
|
strapi2.log.warn(`[Firebase Auth] Migration warning: ${error.message}`);
|
|
368
368
|
}
|
|
369
|
-
if (process.env.FIREBASE_REPORT_ORPHANS === "true") {
|
|
370
|
-
await reportOrphanUsers(strapi2);
|
|
371
|
-
}
|
|
372
369
|
if (process.env.RUN_FIREBASE_MIGRATION === "true") {
|
|
373
370
|
const dryRun = process.env.DRY_RUN === "true";
|
|
374
371
|
strapi2.log.info("");
|
|
@@ -380,12 +377,15 @@ const bootstrap = async ({ strapi: strapi2 }) => {
|
|
|
380
377
|
try {
|
|
381
378
|
strapi2.log.info("[Firebase Auth] Auto-link enabled via FIREBASE_AUTO_LINK_ON_STARTUP");
|
|
382
379
|
await strapi2.plugin("firebase-authentication").service("autoLinkService").linkAllUsers(strapi2);
|
|
380
|
+
await reportOrphanUsers(strapi2);
|
|
383
381
|
} catch (error) {
|
|
384
382
|
strapi2.log.error(`Auto-linking failed: ${error.message}`);
|
|
385
383
|
}
|
|
386
384
|
});
|
|
387
385
|
} else {
|
|
388
|
-
strapi2.log.debug(
|
|
386
|
+
strapi2.log.debug(
|
|
387
|
+
"[Firebase Auth] Startup auto-link disabled (set FIREBASE_AUTO_LINK_ON_STARTUP=true to enable)"
|
|
388
|
+
);
|
|
389
389
|
}
|
|
390
390
|
const pluginConfig = strapi2.config.get("plugin::firebase-authentication");
|
|
391
391
|
const retentionDays = pluginConfig?.activityLogRetentionDays;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-firebase-authentication",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Allows easy integration between clients utilizing Firebase for authentication and Strapi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
"url": "https://github.com/Meta-CTO/strapi-plugin-firebase-auth/issues"
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/Meta-CTO/strapi-plugin-firebase-auth#readme",
|
|
14
|
-
"
|
|
14
|
+
"authors": [
|
|
15
|
+
"Garrett Fritz <garrett@metacto.com>",
|
|
16
|
+
"Felippe Haeitmann <felippe.haeitmann@metacto.com>"
|
|
17
|
+
],
|
|
15
18
|
"keywords": [
|
|
16
19
|
"strapi5",
|
|
17
20
|
"strapi-plugin"
|