ueberauth_auth0
ueberauth_auth0 copied to clipboard
KeyError: key :body not found in: %OAuth2.Error{reason: :timeout}
Hello @achedeuzot,
On rare occasions I've gotten this error: KeyError: key :body not found in: %OAuth2.Error{reason: :timeout}
Here's the stack trace
KeyError: key :body not found in: %OAuth2.Error{reason: :timeout}
File "lib/ueberauth/strategy/auth0.ex", line 154, in Ueberauth.Strategy.Auth0.handle_callback!/1
File "lib/ueberauth/strategy.ex", line 364, in Ueberauth.Strategy.run_handle_callback/2
File "lib/my_app_web/controllers/auth_controller.ex", line 1, in MyAppWeb.AuthController.phoenix_controller_pipeline/2
defmodule MyAppWeb.AuthController do
File "lib/phoenix/router.ex", line 355, in Phoenix.Router.__call__/2
File "lib/my_app_web/endpoint.ex", line 1, in MyAppWeb.Endpoint.plug_builder_call/2
defmodule MyAppWeb.Endpoint do
File "lib/my_app_web/endpoint.ex", line 1, in MyAppWeb.Endpoint."call (overridable 3)"/2
defmodule MyAppWeb.Endpoint do
File "lib/my_app_web/endpoint.ex", line 1, in MyAppWeb.Endpoint.call/2
defmodule MyAppWeb.Endpoint do
File "lib/phoenix/endpoint/cowboy2_handler.ex", line 43, in Phoenix.Endpoint.Cowboy2Handler.init/4
It looks like the code here /lib/ueberauth/strategy/auth0.ex#L154 is expecting an %OAuth2.Response{}, but in this case it's getting an %OAuth2.Error{} which only has a :reason key.
Indeed, it looks like you're having timeouts.
The function called is handle_callback!/1 (notice the bang) so when something fails, it will raise an error which is expected. Still, if you see a better way of surfacing the error, feel free to submit a PR or I'll look into it in the upcoming weeks.
Thanks for the quick response! I'd be happy to do a PR.
In this case my approach would be to pattern match and send it to set_errors! separately. That will let it get passed through to the user's controller as an ueberauth failure.
#/lib/ueberauth/strategy/auth0.ex
case result do
{:ok, client} ->
token = client.token
if token.access_token == nil do
set_errors!(conn, [
error(
token.other_params["error"],
token.other_params["error_description"]
)
])
else
fetch_user(conn, client, state)
end
# Added ↓
{:error, %OAuth2.Error{reason: reason}} ->
set_errors!(conn, [error("OAuth2 error", reason)])
# Added ↑
{:error, client} ->
set_errors!(conn, [error(client.body["error"], client.body["error_description"])])
end
If that approach seems reasonable to you I'll open up a PR soon.
This approach looks good :) Happy to see a PR with this improvement !