Google Datastore comes with a way to encode the key of the entity that is URL safe. This may sound strange at first that a database key api should care about URLs. Since the datastore supports nested data model where an entity can only exist in the context of another, the key of an entity is it’s own key part and the key of it’s parent (which itself is key part + it’s own parent’s key …). It’s like a folder structure /a/b/c. The actual format of the key is the entity name and the int/string id. So, a key can look like this
/User,1234/Mortgage,3394/Payment,7839
This means, there is a payment entity 7839 that’s child of Mortgage entity 3394 that is child of the User 1234. Since this format uses the forward slash, ‘/’, which is used extensively in URLs, using the key as is will have problems. That’s why there are Key.Encode and datastore.DecodeKey(string) methods.
In an app I am working on, the 3rd level entity (user being the first level) can be seen by anyone but not the second level entity. Only the user who is parent of the 2nd level entity can see it. Initially I almost didn’t bother about security just making assumption that the keys are quite random and hard to guess. Then it hit me that when a user has access to the 3rd level key, it’s possible to decode it and construct the 2nd level key and then use the URL that fetches 2nd level entity data (as it would for that person’s own data) and pass the 2nd level encoded key constructed by decoding the 3rd level key. Luckily, I already have the API execute in the context of a valid session and so all I had to do is something like (in golang)
if *entity.GetKey().Parent() != *user.GetKey() {
return error.Error(“You are not authorized to view this data”)
}
With that, the app is secure!