Ueberauth + Guardian redirection from login page

Combining ueberauth, uberauth_google and guardian, I’ve been able to set up an application to:

  • “protect” some URLs behind Guardian Plugs so that an “unauthenticated” function is called in my controller if user is not logged in
  • from there, redirect to a login page
  • from the login page, call “/auth/google” controller to authenticate with Google
  • once authenticated, redirect to “/”

However, this means that a user trying to access “/foo”, when not authenticated, will be redirected to “/”.
Is there a built-in way to support this with guardian / uberauth ?
Or should I deal myself with appending a parameter (like ‘redirect_uri’ ?) to requests to the login_page ? (and if so , how can I pass it to “/auth/google” so that I retrieve in the ueberauth “callback” function ?

1 Like

On the ueberauth “callback” function, you can pattern match with error: https://github.com/ueberauth/ueberauth_example/blob/master/web/controllers/auth_controller.ex#L22

how can I pass it to “/auth/google” so that I retrieve in the ueberauth “callback” function

Set a config option for redirect_uri, like ueberauth_example/config/config.exs at master · ueberauth/ueberauth_example · GitHub

I’m afraid I was not clear on what I was trying to do.

I have Guardian configured to verify that page requests contain a session cookie with a particular jwt.
Logged out users don’t have it, so their request are intercepted by a PageUnauthenticatedController

defmodule PageUnauthenticatedController do
  def unauthenticated(conn, params) do
    Logger.debug("Guardian Page Unauthenticated Handler", [conn: conn, params: params])
    redirect(conn, to: login_path(Endpoint, :login))
  end
end

This redirects to a login page, that contains a button that submits to a /auth/:provider URL
(In my case, I use the auth0 strategy, so the provider will be auth0.)

<form action="/auth/auth0">
        <button class="auth0-sign-in" type="submit">
          <span>Sign in with Auth0</span>
        </button>
</form>

The auth/auth0 route is configured to use MyAuthController :

scope "/auth", do
   get("/:provider", MyAuthController, :request)
   get("/:provider/callback", MyAuthController, :callback)
end

MyAuthController lets Ueberauth deal with the request part, and implement the callbackpart:

defmodule MyAuthController do
  use Xxxx.Web, :controller
  plug(Ueberauth)

  def callback(conn = %{assigns: %{ueberauth_failure: _fails}}, _params) do
    Logger.warn("Authentication failed", conn: conn)

    conn
      |> redirect(to: "/login")
  end

  def callback(conn = %{assigns: %{ueberauth_auth: auth}}, params) do
    WHERE DO I REDIRECT TO ??
 end
end

After the user has entered her credentials in the auth0 page, the callback function is called, but I don’t have any info about where the user came from.
I tried adding a parameter in my login form (I assumed I could redirect to /auth/auth0?foo=bar instead of /auth/auth0, and maybe find the foo=bar part in the connection in the callback phase. But in the redirection dance between my application and auth0, any extra parameters are lost (which makes sense.))

I tried looking at the conn at each stage, but I never seem to get any info about the user’s original request. Should I keep it in session somehow ? Is there a specific parameter I have to configure in the strategy ?

Thanks

I have a plug that stores the person’s current accessed full URL to their session only if it is a GET request except on paths in my /auth/*. Then in the login (in /auth/*) I just read it back and ‘go there’. This means I don’t have to worry about surprise redirects because someone crafted a special URL to an external site or so too. :slight_smile:

3 Likes