If you're using backend processors with Firebase, you probably know not to be authenticating the server with your Firebase secret. Instead you should be using custom tokens.
Many people, ahem, use custom tokens with an "admin" : true
flag in the payload. With the admin flag, Firebase ignores all security rules and allows the user to do anything on the entire Firebase. While very convenient, it's also somewhat insecure. Anyone that happens to get hold of this token has full read/write on your Firebase.
Using Custom Rules with UID's
A better option is to use custom rules that restrict actions to specific UID's. Then, every server should have a unique non-admin token with a unique UID - photos-processor
for example.
Here's how those rules would look:
{
"rules": {
".read": false,
".write": false,
"photos": {
// If the uid is associated with the photo processor, then give it full read/write access to this node.
".read": "auth.uid === 'photo-processor'",
".write": "auth.uid === 'photo-processor'",
// Only the registered user can access their own photos
"$accountsId": {
".read": "$accountsId === auth.uid",
".write": "$accountsId === auth.uid"
}
},
"accounts": {
// If the uid is associated with a processor, then give it full read/write access to this node.
".read": "auth.uid === 'accounts-processor'",
".write": "auth.uid === 'accounts-processor'",
// Only the registered user can access their own account profiles
"$accountsId": {
".read": "$accountsId === auth.uid",
".write": "$accountsId === auth.uid"
}
}
}
}
With the recent discovery of a vulnerability in some JWT (JSON Web Tokens) implementation, a unique UID might not be all that secure either. I don't believe that the Firebase tokens were/are affected by this vulnerability, but who knows what other vulnerability might be lurking out there.
Feature Proposal : IP Address Restrictions
While someone managing to create a bogus token with the right payload is pretty unlikely, there's a more likely scenario: you accidentally commit your token to GitHub or some other repository. Now, anyone that notices this token has full access to your "photos" node in your Firebase. Imagine the havoc they could cause.
So, I have a feature suggestion. I'd like to see Firebase rules that use a special property ip_address
. The ip_address
property could be used in the rules to lock down access to specific servers. This way, if a token is accidentally exposed, someone trying to hack into your Firebase has one more hurdle to overcome. They need to know your restricted IP address and manage to fake it.
Here's what the rules for this new feature might look like:
{
"rules": {
".read": false,
".write": false,
"photos": {
// If the uid is associated with the photo processor & has the correct IP address,
// then give it full read/write access to this node.
".read": "auth.uid === 'photo-processor' && ip_address` === '192.168.1.103",
".write": "auth.uid === 'photo-processor' && ip_address` === '192.168.1.103",
// Only the registered user can access their own photos
"$accountsId": {
".read": "$accountsId === auth.uid",
".write": "$accountsId === auth.uid"
}
},
"accounts": {
// If the uid is associated with the photo processor & has the correct IP address,
// then give it full read/write access to this node.
".read": "auth.uid === 'accounts-processor' && ( `ip_address` === '192.168.1.101' || `ip_address` === '192.168.1.102' )",
".write": "auth.uid === 'accounts-processor' && ( `ip_address` === '192.168.1.101' || `ip_address` === '192.168.1.102' )",
// Only the registered user can access their own account profiles
"$accountsId": {
".read": "$accountsId === auth.uid",
".write": "$accountsId === auth.uid"
}
}
}
}
UPDATE: If you're trying to figure out how to even get a user's IP address using Firebase, see this post. At the top is an update about a project on how to do this.