12

我有一個使用Firebase數據庫的小型個人Firebase Web應用程序。我想從一個特定的域中將這個應用程序安全(鎖定)給任何用戶。我想通過Google進行身份驗證。我不清楚如何將規則配置爲「只有來自單個特定域(例如@foobar.com)的用戶才能讀取和寫入此數據庫」。我發現有一個問題的一部分:很難用足夠的信息啓動一個數據庫來使這個用例工作,我需要在認證時知道用戶的電子郵件,但是auth對象不包含電子郵件這似乎是一個雞雞蛋問題,因爲我需要編寫引用數據庫中的數據的Firebase規則,但由於我的用戶無法寫入數據庫,因此該數據尚不存在。)如何將Firebase數據庫鎖定到來自特定(電子郵件)域的任何用戶?

如果auth有電子郵件,那麼我可以很容易地編寫規則。

提前致謝!

+1

問題:當你說從一個域鎖定,這是否意味着鎖定到一個單一的供應商,像谷歌和它的字面意思是隻允許從myDomain的用戶訪問您的火力地堡即測試@ myDomain的認證通過密碼是好的,但不允許通過谷歌認證的事物@另一個域名。 – Jay

+0

我的意思是,「來自@ foobar.com的任何人,經Google驗證/認證,都可以讀取和寫入數據庫」 –

+0

您是否確實需要規則?在某些時候,用戶必須輸入他們的電子郵件地址以便能夠登錄或創建他們的帳戶,所以您不能在輸入時解析它,並拒絕任何沒有@ foobar.com的帳戶作爲域名? – Jay

回答

28

如果您使用的是新的Firebase,現在可以使用了,因爲email在安全規則中可用。

在安全規則中,您既可以訪問電子郵件地址,也可以訪問其電子郵件地址以及是否驗證,這使得一些很好的用例成爲可能。有了這些規則,例如只有通過身份驗證,驗證的Gmail用戶可以寫自己的個人資料:

{ 
    "rules": { 
    ".read": "auth != null", 
    "gmailUsers": { 
     "$uid": { 
     ".write": "auth.token.email_verified == true && 
        auth.token.email.matches(/.*@gmail.com$/)" 
     } 
    } 
    } 
} 

您可以輸入您的項目的Firebase Database console這些規則。

+0

非常感謝您的更新! –

+1

https://firebase.google.com/docs/reference/security/database/#authtoken包含'auth.token'中提供的文檔。 –

+1

看到這樣一個例子,從數據庫的根目錄中取出'@ gmail.com',例如'my_database/acceptable_domains /',例如,他們只想打開他們的應用程序到少數幾個郵件提供商。如授權的學校和企業。 – Hobbyist

2

警告:不要相信這個答案。就在這裏討論。

tldr:我不認爲這是可能的,沒有運行自己的服務器。

這是我嘗試迄今:

{ 
    "rules": { 
    ".read": "auth.provider === 'google' && root.child('users').child(auth.uid).child('email').val().endsWith('@foobar.com')", 
    ".write": "auth.provider === 'google' && root.child('users').child(auth.uid).child('email').val().endsWith('@foobar.com')", 
    "users": { 
     "$user_id": { 
     ".write": "auth.provider === 'google' && $user_id === auth.uid && newData.child('email').val().endsWith('@foobar.com')" 
     } 
    } 
    } 
} 

我相信上面的說「只有讓人們創建一個新用戶,如果他們通過谷歌認證,正在努力編寫成themselve數據庫節點($user_id === auth.uid )和他們的電子郵件在foobar.com結束「。

但是,有一個問題被指出:任何Web客戶端都可以在將消息發送到Firebase之前輕鬆更改其電子郵件(使用開發控制檯)。因此,我們無法信任存儲在Firebase中的用戶條目的數據。

我認爲我們唯一可以信任的是規則中的auth對象。那個auth對象由Firebase的後端填充。而且,不幸的是,auth對象不包含電子郵件地址。

爲了記錄在案,我將我的用戶是這樣的:

function authDataCallback(authData) { 
    if (authData) { 
    console.log("User " + authData.uid + " is logged in with " + authData.provider + " and has displayName " + authData.google.displayName); 
    // save the user's profile into the database so we can list users, 
    // use them in Security and Firebase Rules, and show profiles 
    ref.child("users").child(authData.uid).set({ 
     provider: authData.provider, 
     name: getName(authData), 
     email: authData.google.email 
    }); 

正如你也許能夠想象,一個確定的用戶可以(通過使用DevTools,爲例子)覆蓋的email這裏的價值。

+0

正如你的發現:'.write'規則可以控制誰可以寫入一個位置,'.validate'規則可以驗證他們寫的是一個有效的電子郵件地址。但是沒有辦法在安全規則中驗證它實際上是該用戶的電子郵件地址。爲此,您需要運行一些受信任的代碼(通常位於服務器上),該代碼會將此已驗證的電子郵件地址寫入數據庫中的一個(否則爲只讀)位置。 –

1

這裏是我的數據庫工作正常的代碼,我已經設置規則,只有我的公司電子郵件可以讀取和寫入我的firebase數據庫的數據。

{ 
    "rules": { 
    ".read": "auth.token.email.matches(/.*@yourcompany.com$/)", 


     ".write": "auth.token.email.matches(/.*@yourcompany.com$/)" 
     } 
    } 
0

正在爲我工​​作的代碼。

export class AuthenticationService { 

    user: Observable<firebase.User>; 

    constructor(public afAuth: AngularFireAuth) { 
     this.user = afAuth.authState; 
    } 

    login(){ 
     var provider = new firebase.auth.GoogleAuthProvider(); 
     provider.setCustomParameters({'hd': '<your domain>'}); 
     this.afAuth.auth.signInWithPopup(provider) 
     .then(response => { 
      let token = response.credential.accessToken; 
      //Your code. Token is now available. 
     }) 
    } 
} 
相關問題