firebase-functions: Include `context.auth` for Firestore triggers
Version info
firebase-functions: ^2.0.2 firebase-tools: ^4.0.2 firebase-admin: ^5.13.1
Test case
functions.firestore
.document('test/model')
.onWrite((data, context) => {
expect(context.auth.uid).toEqual('the-user-id')
})
Steps to reproduce
Here’s a test case at brianmhunt/bug-reports on the firestore-functions-auth
branch. Just clone, yarn install
and yarn test
(or npm ^^
).
Note that the test case is not testing production behaviour, but the firebase-functions-test
behaviour, however I would expect the test and production behaviour to be fixed in tandem.
Expected behavior
The EventContext
for a Firestore call should contain the user authentication information, as it does with Callable and Realtime database calls, i.e. context.auth
should be populated.
Actual behavior
The context.auth
is undefined for firestore onWrite
and related functions.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 74
- Comments: 47 (6 by maintainers)
Hi there again everyone - another update. It has been decided that unfortunately native support for
context.auth
for Firestore triggers will not be implemented due to technical constraints. However, there is a different solution in the works that hopefully will satisfy your use case, but I cannot share details. On this forum we generally keep open only issues that can be solved inside the functions SDK itself - I’ve kept this one open since it seemed important and I wanted to provide some updates on the internal bugs tracking this work. Now that a decision has been reached, I’m going to close this out. Thanks again for everyone’s patience and I’m sorry I don’t have better news. Please use the workaround referenced in https://github.com/firebase/firebase-functions/issues/300#issuecomment-428593485.Hi this feature is a deal breaker for me, no concept of who made an update inside the trigger is an oversight, at present this hinders our ability to select firestore as a platform, I look forward to hearing about this feature coming available. asap
Hi everyone, thanks for your patience! This feature request is unfortunately more involved than we originally thought, and will take longer to implement. However, we are doing our best to move this forward.
Internal bug reference: 68792946
Hi, this is a good feature request, and it is on our backlog.
Hi, would really appreciate an update on this, seems like a pretty important feature. Cheers.
What’s the status on this feature?
Hi everyone, I checked back in on this issue to see how it’s progressing. Still blocked, but I linked to this thread and urged the priority of this issue to be increased. Let’s see how it goes. Will post back here with updates when I have them. Thanks for your patience!
@adamduren it wasn’t mentioned because the scope of the requirement is bigger than just user-agent validation/authorization checks.
Consider the following example: I have an object A that can be accessed by a team of users. It is important in such a system to keep a record of who deleted object A. Ideally you’d be able to write an onDelete trigger to add a record - personB, deleted object X, datetime etc.
However, since we don’t have access to who the actor is in triggers… we’d have to do this client side for every delete action. This means if you write a web app and a mobile app, you’d have to duplicate the logic in both clients to log the actors, rather than using the trigger to take care of it.
Just ran into this issue while implementing Firestore Cloud Functions.
@thechenky Is there an update about the different solution?
Thanks!
This is not good. It makes what I would consider a whole class of functions (audit logs, history, etc.) impossible. None of the proposed solutions are clean either. I guess we can just grit our teeth and make a REST API out of other functions. It really does feel like I have just stepped in a dirty puddle on the otherwise nice path that has been my journey with Firebase
Hey @laurenzlong just wanted to follow up on this and see if there’s any progress or if there’s anything the community can do to help move things along. I’d love to move some projects over to firestore but not having this auth data in cloud functions makes it impossible to handle some security setup I use. I’d be happy to take a look and open a PR if there was some direction on what needed to get going. Thanks in advance.
Thanks for the update @thechenky. I can only imagine the the design constraints for a system like Firestore and the challenges that present for the issue here, and while this didn’t get resolved the way everyone hoped I am grateful for the effort to resolve this issue and keep everyone informed.
Summary of how I solved this / a workable solution similar/same as (?) Comment #300:
On client Add logged in/current user’s uid (e.g. as
creatorId
) to entity they’re creating. Access this uid by storing thefirebase.auth().onAuthStateChanged()
User object in your app state.In Firebase Firestore/Database Add a Security Rule to
create
to validate that the client-suppliedcreatorId
value is the same as the authenticated user’s uid; Now you know the client isn’t spoofing thecreatorId
and can trust this value elsewhere.e.g.
In Firebase Functions Add an
onCreate
trigger to your created entity type to use the client-supplied, and now validated,creatorId
to look up the creating user’s profile info, and associate/append this info to the new entity doc.This can be accomplished by:
Creating a
users
collection and individualuser
documents when new accounts are created, and populating the newuser
doc with app-useful fields (e.g.displayName
). This is required because the fields exposed by the Firebase Authentication system are insufficient for consumer app uses (e.g.,displayName
andavatarURL
are not exposed) so you can’t just rely on looking up the creating user’s info that way.e.g. (using ES6)
creatorId
value, and usefuluser
objects, add anonCreate
trigger to your entity type (or all your created entities) to look up the creating user’s info and append it to the created object.This clearly leads to a lot of duplicated user info data throughout your system – and there’s a bit of clean up you can do ('creatorId` is duplicated on the created entity in the above implementation) – but now it’s super easy to show who created what throughout your app, and appears to be ‘the Firebase way’.
Hope this helps. I’ve found Firebase to be super amazing in some ways, and make some normally easy things (like this) harder than they ‘should’ be; on balance though am a major fan.
Is there any workaround for this feature? We really need this feature to compensate user some reward whenever a user creates a new record.
It’s already documented in the official reference: https://firebase.google.com/docs/reference/functions/functions.EventContext#.auth
@adamduren yeah, we actually went that route but it has a lot of disadvantages. Some you identified, others:
I’m not exactly happy this feature never made it.
The only hacky workaround I can think of, is having a
deleted
field on the document, which the client filters out, and then have theonUpdate
trigger log that the document was deleted, and then actuallydelete()
the document.Hideous.
@thechenky another use case which I can’t find an easy workaround: when I need to know which user deleted a document.
For
create
andupdate
triggers, I can add a field for identifying the user who made a change. However, that’s not possible when deleting a document. Or am I mistaken? Is there a way to know which user deleted a document?Not having this feature is really frustrating. I hope you reconsider and implement it in future versions.
@thechenky Hi! You mentioned there would be a different solution that might be able to satisfy our use cases. Was it implemented already?
I have a use case where
revisions
collection including theiruid
;Currently, I have to add a
latestEditor
field including the user’s UID but it would be much easier to just have thecontext.auth
option to get the UID.Surprised I didn’t see it mentioned in this thread, but if you have to do user-agent validation/authorization checks, that logic can be managed within Firestore rules, which does have access to the auth context
@mqln unfortunately this issue is blocked on a list of other issues that need to be resolved before this is implemented.
Hello there, I created a Firestore trigger that logs write actions into a separate
history
collection, and the only thing missing is a safe way to identify the user. I hoped theEventContext.auth
field would work while the client is signed in with a JWT. The only solution I found yet is to require a user ID in Firestore Security Rules and compare it with the JWT, then the value passed to the trigger would be safe. But even if the trigger can get the user ID and put it into its logging collection, it can’t remove it from the targeted collection without performing a new request, which will, of course, cost something.I was developing a tracking system about who made a difference for a specific document. I guess there are use cases where we cannot find a programmatical workaround.
@thechenky Thanks for the info. At least, the community would be sure that this feature eventually will be shipped.
I ended up doing this for now: https://stackoverflow.com/a/50842161/637751