按需医生应用三类用户的Firebase认证解决方案咨询
Great question—building a multi-role Doctor-on-Demand app with Firebase is totally feasible, and I’ve worked through similar auth setups before. Let’s break down the implementation, starting with the custom auth fields and role management you’re asking about.
Firebase Auth alone has limited space for custom data, so we’ll combine it with Firestore for extended profiles, plus custom claims for quick role-based access checks.
a. Use Firebase Auth Custom Claims for Role Checks
Custom claims are lightweight, encrypted data attached to the user’s ID token—perfect for fast role validation (like routing users to the right dashboard or restricting API access).
Here’s how to set them up using the Firebase Admin SDK (run this in Cloud Functions or your backend—never do it client-side, since it requires admin privileges):
const admin = require('firebase-admin'); async function assignUserRole(uid, role) { // Validate role to prevent invalid values const validRoles = ['patient', 'doctor', 'admin']; if (!validRoles.includes(role)) throw new Error('Invalid role type'); await admin.auth().setCustomUserClaims(uid, { role }); }
On the frontend, you can fetch the claims to handle routing immediately after login:
firebase.auth().onAuthStateChanged(async (user) => { if (user) { const idTokenResult = await user.getIdTokenResult(); const userRole = idTokenResult.claims.role; // Redirect to role-specific dashboard switch(userRole) { case 'admin': window.location.href = '/admin-dashboard'; break; case 'doctor': window.location.href = '/doctor-dashboard'; break; default: window.location.href = '/patient-dashboard'; } } });
b. Store Extended Custom Fields in Firestore
Firebase Auth only lets you save basic fields (email, displayName, photoURL), so use a Firestore users collection to store role-specific data:
- Each document ID matches the user’s Firebase Auth UID
- Include a
rolefield for easy querying, plus role-specific details
Example document structure:
users/{uid} - role: "doctor" - fullName: "Dr. Sarah Johnson" - phoneNumber: "+1234567890" - doctorDetails: { licenseNumber: "MED-12345", specialty: "Cardiology", availableSlots: ["2024-05-20T10:00", "2024-05-20T14:00"] }
When a user registers, after creating their Auth account, save their full profile to Firestore:
// Frontend registration handler async function registerUser(email, password, role, profileData) { try { const { user } = await firebase.auth().createUserWithEmailAndPassword(email, password); // Call a Cloud Function to set the role claim (secure, admin-only) await firebase.functions().httpsCallable('assignUserRole')({ uid: user.uid, role }); // Save extended profile to Firestore await firebase.firestore().collection('users').doc(user.uid).set({ role, ...profileData, createdAt: firebase.firestore.FieldValue.serverTimestamp() }); // Redirect logic here... } catch (err) { console.error('Registration failed:', err); // Show user-friendly error message } }
c. Secure Role Assignment with Cloud Functions
Never let clients set roles directly—use a Cloud Function with admin checks to ensure only existing admins can assign roles:
exports.assignUserRole = functions.https.onCall(async (data, context) => { // Verify the requester is an admin if (!context.auth || context.auth.token.role !== 'admin') { throw new functions.https.HttpsError('permission-denied', 'Only admins can assign roles'); } const { uid, role } = data; const validRoles = ['patient', 'doctor', 'admin']; if (!validRoles.includes(role)) { throw new functions.https.HttpsError('invalid-argument', 'Role must be patient, doctor, or admin'); } await assignUserRole(uid, role); return { message: `Successfully assigned ${role} role to user ${uid}` }; });
Lock down your data to ensure users only access what they’re allowed to. Example rules:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // Users can only access their own profile match /users/{uid} { allow read, write: if request.auth != null && request.auth.uid == uid; } // Doctors can read patient profiles (adjust based on your app's needs) match /users/{uid} { allow read: if request.auth != null && request.auth.token.role == 'doctor' && resource.data.role == 'patient'; } // Admins have full access to all data match /{document=**} { allow read, write: if request.auth != null && request.auth.token.role == 'admin'; } } }
- Doctor Verification: Add a pending state for new doctor registrations—set their role to 'pending_doctor' initially, then let admins approve and switch it to 'doctor'.
- Email Verification: Enable Firebase’s email verification for all users to reduce fake accounts, especially critical for doctors.
- Claim Refreshes: Custom claims are cached in the ID token, so if you update a user’s role, they’ll need to log out and back in (or call
user.getIdToken(true)to force a refresh). - Session Handling: Use
onAuthStateChangedto listen for auth state changes and redirect users if their role or authentication status changes.
内容的提问来源于stack exchange,提问作者user8176988

