0

Ive made a project that can be found here:

https://github.com/rootkc/phx_auth_api

When I try to post to:

http://0.0.0.0:4000/api/login

with the body:

{ "user": { "username": "kenneth", "password": "kenneth" } }

That is a user that is in the database. I get the response:

{
"data": {
    "token": "eyJhbGciOiJIUzUxM[...]gbPVHTsSvrCA"
}

}

When i then put that token in the header: Àuthorization: :token of the call http://0.0.0.0:4000/api/users that has the Guardian pipeline plug I get back the message: unauthenticated

And i have no idea, what i'm doing wrong. This is my first real Phoenix project and i tried to follow various guide but the {:guardian, "~> 1.0-beta"} seems to be quite new, with bad documentation.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • Since there is an open issue i guess i'm not blaming anyone: https://github.com/ueberauth/guardian/issues/386. –  Nov 14 '17 at 08:29
  • I wrote a tutorial that is exactly for this topic (PHX 1.3, Guardian 1): https://medium.com/@tylerpachal/session-authentication-example-for-phoenix-1-3-using-guardian-1-0-beta-a228c78478e6 – Tyler Nov 14 '17 at 19:44
  • I did look alot at your article - but that is not for API authentication. But i got it to! –  Nov 15 '17 at 16:09
  • It shouldn't make any difference if you are authenticating API requests or not. Everything comes in through a pipeline and can have rules on that pipeline. Glad you got it working though. – Tyler Nov 15 '17 at 21:48

3 Answers3

1

Believe or not, but Guardian is very well documented library and it's very popular for Elixir and Phoenix projects.

Please check this article for simple API authentication.

How exactly you wanted to put the header? You should use Guardian's already defined functions.

Guardian.encode_and_sign returns you {:ok, token, map} and you need this token to be passed to the header. Then, guardian uses plug VerifyHeader that expects token to be in form

Authorization: token

It's totally up to you how you want to mix up usage of guardian functions, but article from above is very nice introduction.

Edit Assuming that you are running Elixir 1.5.x, you can try to run your server in IEx and then debug what's going on: iex -S mix phx.server. Simply use break! controller_name.action_name and try to click this action in webbrowser / postman etc.

Also you can debug Guardian functions this way.

Edit 2

In PhxAuthApi.Auth.Guardian you don't encode the token anywhere, but in PhxAuthApi.Auth.Pipeline you request that e.g. it has particular claims, but you didn't provide them.

You over engineered this auth by creating your custom modules that doesn't work properly.

PatNowak
  • 5,721
  • 1
  • 25
  • 31
  • I tried to follow this example https://github.com/oskar1233/texts/blob/master/Guardian1.0/Guardian.md provided in an open github issue on the Guardian page. But i encode the token using encode_and_sign in the SessionController. When i try to decode the JWT using https://jwt.io/ it has the payload "typ" => "access". So i guess when i call the pipeline with Authorization: token in the header. i guess that should work.. –  Nov 14 '17 at 08:37
  • 1
    The article you linked is from 2015, hasn't Guardian changed a lot since then? – Tyler Nov 14 '17 at 19:43
  • Also some of the things you linked are from 0.14 and OP specifically asked for Guardian 1.0 – Tyler Nov 14 '17 at 20:04
0

you have this in your pipeline:

plug Guardian.Plug.VerifyHeader, claims: %{"typ" => "access"}, realm: :none

which means your header needs to be:

Authorization: none: <token>

because that is what is in Guardian.Plug.VerifyHeader:

def init(opts \\ %{}) do
  opts_map = Enum.into(opts, %{})
  realm = Map.get(opts_map, :realm)
  if realm do
    {:ok, reg} = Regex.compile("#{realm}\:?\s+(.*)$", "i")
    Map.put(opts_map, :realm_reg, reg)
  else
    opts_map
  end
end

my guess you need to remove realm: :none setting so your token can be properly parsed.

ash
  • 711
  • 4
  • 8
0

I had an typo in my Pipeline. Now everything works as expected.