Im trying to pass from information from my resolver function to my middleware such that I can set a cookie in the response.
The use-case is I want to generate an Oauth2 authorization link which allows the client to begin an Oauth2 flow with a third party. I want to generate a "state" object which I can set as a cookie in the response.
I've tried calling
%{resolution | context: state}
within the resolver but unfortunately that doesn't seem to pass that state down.
Here is a simplified example of my resolver function
def get_oauth_link(_parent, _args, resolution) do
state = random_string(10)
part_one = "https://github.com/login/oauth/authorize"
part_two = "?client_id=XXX"
part_three = "&redirect_uri=http://localhost:3000/login/callback"
part_four = "&state=" <> state
part_five = "&scope=user:email"
url = part_one <> part_two <> part_three <> part_four <> part_five
# try to add the state to the resolution to
%{resolution | context: state}
{:ok, url}
end
And then in my schema
@desc "Get oauth link"
field :oauthlink non_null(:string) do
resolve(&Resolvers.OauthResolver.get_oauth_link/3)
# middleware after resolution to set a cookie with the provided state
middleware fn resolution, _ ->
# Here i want to extract the state generated in
# the resolver and add to the context
IO.inspect(resolution, label: "Inside resolution")
end
end
Im expecting to be able to set the cookie in the "absinthe_before_send" method as documented here: https://hexdocs.pm/absinthe_plug/Absinthe.Plug.html#module-before-send
Whats the best way of doing this? The approach above seems intuitive to me but the state is not available in the post-resolution middleware.
You cannot change the resolution in a resolver function.
You can, however, change the resolution in the middleware. That's what middlewares are for. The post resolver middleware resolution will have a value
field which contains result from the resolver function (without the :ok
or :error
atom).
What you can do is return both state
and url
from your resolver function, then in your post resolution middleware, extract the state from the resolution value
field and reset the resolution value
to the url. Like this:
def get_oauth_link(_parent, _args, resolution) do
state = random_string(10)
part_one = "https://github.com/login/oauth/authorize"
part_two = "?client_id=XXX"
part_three = "&redirect_uri=http://localhost:3000/login/callback"
part_four = "&state=" <> state
part_five = "&scope=user:email"
url = part_one <> part_two <> part_three <> part_four <> part_five
{:ok, %{url: url, state: state}} # return state and url
end
field :oauthlink, non_null(:string) do
resolve(&Resolvers.OauthResolver.get_oauth_link/3)
middleware fn %{value: %{state: state, url: url}=resolution, _ ->
resolution
|> Map.put(:context, state) # set context using state
|> Map.put(:value, url) # reset value to url
end
end