ash_graphql update without authorizing the read action
I have a user ash resource (not using ash_authentication here) whose read action is gated by policies. I'm adding a reset_password action, which will take a reset token we emailed to the user and their new password, and if the token matches, will update their password (all of this via ash_graphql from an SPA).
Because of the nature of this workflow, there will necessarily be no actor present when this action is called. In direct elixir code (such as in unit tests), this works great:
but via graphql mutation, this becomes an issue because ash_graphql uses the resource's read action, which is gated by policies., so the read phase of the graphql transaction fails because it is filtering based on the actor (which does not exist here).
I'm wondering if it's possible to disable authorization on just the read action for a graphql call? Or is my only option in this case to create a separate read action w/ no policies and use
read_action :unfiltered_read or something?9 Replies
I'm imagining something like
authorize_read? on the update DSL optionsHm, either that or creating a generic action, where you just do the same read with
authorize?: falseYeah, I was considering that
that = create a read action without any policies 😛
a generic action feels kinda annoying, since it requires wiring everything up manually, but seems like it's probably the most explicit way of doing this in the current version of ash_graphql.
Would a PR be accepted that added an
authorize_read? opt on the update DSL options?Hmm...there is another way to do it
You can set the
read_action option to a read action that allows all reads
But that's not ideal because you could accidentally expose the record
Actually, you don't want to do what you're trying to do I think
You do want a generic action
You're exposing the ability to read the user record and any other fields just by knowing the email rightsI had considered that. On its face it feels potentially problematic, but thinking further, they did just reset the user's password, so they'd be able to get access to that user record by just going and logging in with the password they just reset to, right? So in practice kinda feels like it'd be fine
But I can see why a generic action is potentially a bit of a tighter representation of this. I'll probably go that route
oh, it requires current password?
Then yeah its fine in that case
well, 2 use cases. One is a token we send via email to validate identity (doesn't require an actor because you could be logged out, like forgot password situation). One is provide current password + new password (does require an actor, like a PW reset whilw logged in).
Regardless, I ended up going with the generic action route anyways.
but in both use cases, you're providing something that confirms you are allowed to change the user's password, which would also imply access to the user record itself. Although, I could see an argument that depending on policies and/or field policies you might not be able to access "your own" user record and/or all fields of it, so exposing it fully unauthorized is dangerous.
In our case the policies are pretty simply just that you can always read your own user record though so it's kinda fine