Ionic+Firebase谷歌登录的域名限制安全实现方案咨询
Great question—security is non-negotiable here, so let’s break this down clearly.
First: Is client-side domain checking safe?
Absolutely not. Client-side code (like the split-and-check logic in your example) is fully exposed to users. Anyone with basic dev tools can modify your Ionic app’s JavaScript to bypass the domain check and directly navigate to AuthenticatedPage. This is a huge security gap—never rely on client-side logic alone to restrict access to protected resources.
The Secure Approach: Server-Side Validation with Firebase
Firebase gives you all the tools to enforce domain restrictions safely, using a combination of Cloud Functions and Custom Claims. Here’s how to implement it properly:
Step 1: Validate User Domains with a Firebase Cloud Function
We’ll write a server-side function that triggers whenever a new user signs up. It checks if the user’s email matches your company domain, and either marks them as authorized or removes their account if they’re not.
Here’s the Cloud Function code (TypeScript example):
import * as functions from "firebase-functions"; import * as admin from "firebase-admin"; admin.initializeApp(); // Trigger when a new user is created export const validateCompanyEmployee = functions.auth.user().onCreate(async (user) => { const allowedDomain = "neutron.ca"; const userEmail = user.email; if (userEmail && userEmail.endsWith(`@${allowedDomain}`)) { // Add a custom claim to mark the user as authorized await admin.auth().setCustomUserClaims(user.uid, { isCompanyEmployee: true }); functions.logger.log(`User ${user.uid} (${userEmail}) validated as company employee`); } else { // Delete unauthorized users immediately await admin.auth().deleteUser(user.uid); functions.logger.log(`Deleted unauthorized user ${user.uid} (${userEmail})`); } });
Deploy this function to Firebase (run firebase deploy --only functions in your terminal) and it will automatically handle user validation every time someone signs up.
Step 2: Update Your Ionic Client to Check Custom Claims
Now, in your Ionic app, after a user signs in, you’ll fetch their custom claims to confirm they’re authorized. Only then do you let them access protected pages:
import { AlertController } from '@ionic/angular'; // Inject AlertController in your component constructor constructor(private afAuth: AngularFireAuth, private navCtrl: NavController, private alertController: AlertController) {} login() { this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider()) .then(async (res) => { const user = res.user; if (!user) return; // Fetch the user's ID token to access custom claims const idTokenResult = await user.getIdTokenResult(); const isAuthorized = idTokenResult.claims.isCompanyEmployee; if (isAuthorized) { // Navigate to protected page this.navCtrl.setRoot(AuthenticatedPage); } else { // Sign out unauthorized users and show alert await this.afAuth.auth.signOut(); this.showUnauthorizedAlert(); } }) .catch((err) => { // Handle errors (e.g., user was deleted for invalid domain) if (err.code === "auth/user-not-found") { this.showUnauthorizedAlert(); } else { console.error("Login error:", err); } }); } private async showUnauthorizedAlert() { const alert = await this.alertController.create({ header: "Unauthorized", message: "Only employees with a neutron.ca email can access this app.", buttons: ["OK"] }); await alert.present(); }
Step 3: Lock Down Backend Resources with Firebase Security Rules
Even if someone somehow bypasses the client-side check, you need to ensure they can’t modify or access backend data (like submitted timesheets). Use Firebase Security Rules to enforce access only for authorized users.
For example, if you’re using Firestore to store timesheets, add this to your firestore.rules file:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // Restrict timesheet access to authorized company employees match /timesheets/{timesheetId} { allow read, write: if request.auth.token.isCompanyEmployee == true; } } }
Bonus: Enhance User Experience (But Not Security)
You can add client-side domain checking as a pre-check to give users immediate feedback, but remember this is only for UX—not security. For example:
// Pre-check email domain before initiating login (optional UX touch) checkEmailDomain(email: string) { const allowedDomain = "neutron.ca"; return email.endsWith(`@${allowedDomain}`); } // Use in your login flow: if (!this.checkEmailDomain(userInputEmail)) { this.showUnauthorizedAlert(); return; } // Proceed with Google login
This saves users from going through the entire Google login flow only to be rejected, but it doesn’t replace the server-side validation.
内容的提问来源于stack exchange,提问作者MF9

