ueberauth / guardian

Elixir Authentication
MIT License
3.44k stars 381 forks source link

How do I redirect to a sign in page? #398

Closed mitkins closed 7 years ago

mitkins commented 7 years ago

I'm upgrading my app to version 1. I've setup the following pipeline to prevent unauthenticated users from accessing particular pages:

defmodule Zoinks.Guardian.AuthPipeline do
  @claims %{typ: "access"}

  use Guardian.Plug.Pipeline,
    otp_app: :zoinks,
    module: Zoinks.Guardian,
    error_handler: Zoinks.Guardian.AuthErrorHandler

  plug Guardian.Plug.VerifySession, claims: @claims
  plug Guardian.Plug.EnsureAuthenticated
  plug Guardian.Plug.LoadResource, ensure: true
end

And here's my error handler:

defmodule Zoinks.Guardian.AuthErrorHandler do
  import Plug.Conn

  def auth_error(conn, {type, _reason}, _opts) do
    body = Poison.encode!(%{message: to_string(type)})
    send_resp(conn, 401, body)
  end
end

In the past (0.14) I had an unauthenticated function handler in the Controller - which allowed me to use conn.put_flash and conn.redirect. With the new error handler, how do I redirect to a login page?

oskar1233 commented 7 years ago

I think you can create module like AuthErrorController, which will be either Phoenix's controller and error handler in terms of Guardian.

I would add use ZoinksWeb, :controller to the module, then think about naming and adding it into Web namespace.

hassox commented 7 years ago

You can still use a function in the controller to handle errors. Keep the pipeline you have in place and in your controller set a different error handler.

defmodule ZoinksWeb.SomeController do
   # snip

  plug Guardian.Plug.Pipeline, error_handler: __MODULE__

  # snip

  def auth_error(conn, {type, reason}, _opts) do
    do_stuff(conn)
  end
end

The error handler can be set upstream in your pipeline module. The error handler module is at that point put into the conn struct. If you use the Guardian.Plug.Pipeline plug you can change it for downstream plugs.

mitkins commented 7 years ago

So I could create an AuthErrorController like @oskar1233 suggests and set that in my controller (as pointed out by @hassox) while still having Zoinks.Guardian.AuthErrorHandler as the global handler?

hassox commented 7 years ago

Yes you could do it that way. When you use the pipeline plug you setting the error handler for all downstream plugs. You can change it out as often as you need to.

mitkins commented 7 years ago

Cool. Thanks!