danww

danww

Hi there,

I have an Elm frontend app, performing user login and token creation with Auth0 Lock, and then performing requests to a Phoenix API on the backend, passing the JWT token from Elm to Phoenix in an “Authorization: Bearer ” header.

I want the Phoenix API to be able to verify the supplied token in order to auth the request from the client app.

I’m currently using Guardian(API Reference — Guardian v2.4.0), configured along these lines:
Can I verify a JWToken created by Auth0 ? · Issue #211 · ueberauth/guardian · GitHub

I’m new to Phoenix.
I can’t get past ‘plug Guardian.Plug.EnsureAuthenticated’.
I’m not sure how to debug/inspect router/pipeline.
Ideally, I’d like Guardian.Plug.EnsureAuthenticated to reside in the pipeline, rather than in each controller.

Am I correct in assuming that Guardian will actually verify the supplied token with Auth0?
Because there doesn’t seem to be any provision in the config for the Auth0 ‘client_id’, which I expect would be necessary.

Showing Posts 1 to 10

krapans

krapans

How do you pass in the request from front-end the JWT token?

danww

danww OP

I’m adding a header (Authorization: Bearer <token>) to the request.
I understand Guardian should find and verify this token with the plug Guardian.Plug.VerifyHeader, realm: "Bearer" in the pipeline. I’m using the same Auth0 secret in the config for both client and server.

krapans

krapans

Ok, from this what you are saying everything sounds fine. I guess you need provide some code examples, so maybe then I could check out it and give you feedback.

danww

danww OP

Okay - here’s my code. Let me know if I’ve missed anything out.

config.exs

# Configures Guardian
config :guardian, Guardian,
  allowed_algos: ["HS256"],
  verify_module: Guardian.JWT,
  issuer: <Auth0 domain, same as is used client-side>,
  verify_issuer: true,
  secret_key: <Auth0 client secret, same as is used client-side for token generation>,
  serializer: MyApp.GuardianSerializer

###router.ex

  # pipeline for api
  pipeline :api do
    plug :accepts, ["json"]
    plug Guardian.Plug.VerifyHeader, realm: "Bearer "
    plug Guardian.Plug.EnsureAuthenticated
    plug Guardian.Plug.LoadResource
  end

Serializer

defmodule MyApp.GuardianSerializer do
  @behaviour Guardian.Serializer
  def for_token(id), do: {:ok, id}
  def from_token(id), do: {:ok, id}
end
krapans

krapans

For me, this looks like this plug Guardian.Plug.VerifyHeader, realm: "Bearer"

And Serializer like this

defmodule MyApp.GuardianSerializer do
  @behaviour Guardian.Serializer

  alias MyApp.Repo
  alias MyApp.User

  def for_token(account = %User{}), do: { :ok, "Account:#{account.id}" }
  def for_token(_), do: { :error, "Unknown resource type" }

  def from_token("Account:" <> id), do: { :ok, Repo.get(User, id) }
  def from_token(_), do: { :error, "Unknown resource type" }
end
danww

danww OP

I currently don’t have Ecto or a Repo set up - not sure I’ll need one, since this API is going to talk straight to another third-party API, so the Serializer isn’t really required, in my case.

I’m still not getting past the VerifyHeader plug - EnsureAuthenticated is failing.
I’m thinking my issue is around the Guardian config. I’m wondering if I’m missing something.

bryanjos

bryanjos

Was on a project recently with auth0 and guardian and got it to work. I think maybe try setting verify_issuer to false

danww

danww OP

I started from the beginning, setting up Guardian from scratch, and it worked.
I’m still not clear why it wasn’t working in the first instance.

If anyone is interested, I did the following:

mix.exs:

  • Added Guardian.
...
def application do
  [mod: {MyApp, []},
   applications: [:phoenix, ..., :guardian, ...]]
end

...

defp deps do
  [{:phoenix, "~> 1.2.1"},
   ...,
   {:guardian, "~> 0.14"}]
end

…then ran mix deps.get

config.exs

  • set allowed_algos to HS256
  • set issuer to Auth0 domain
  • set verify_issuer to false. This may have been what solved it, although I did try changing this in my initial attempt.
  • set secret_key to Auth0 client secret
  • set up my own serializer - see next step.
...
config :guardian, Guardian,
  allowed_algos: ["HS256"], # optional
  verify_module: Guardian.JWT,  # optional
  issuer: <Auth0 domain>,
  ttl: { 30, :days },
  allowed_drift: 2000,
  verify_issuer: false,
  secret_key: <Auth0 client secret>,
  serializer: MyApp.GuardianSerializer

...

serializer.ex

  • I’m not getting anything in/out of the token at this point, so this is not of any significance, just yet
defmodule MyApp.GuardianSerializer do
  @behaviour Guardian.Serializer

  def for_token(id), do: {:ok, id}
  def from_token(id), do: {:ok, id}

end

router.ex

  • Added the following Guardian plugs to the exisiting :api pipeline, as follows
...
pipeline :api do
  plug :accepts, ["json"]
  plug Guardian.Plug.VerifyHeader, realm: "Bearer"
  plug Guardian.Plug.EnsureAuthenticated
  plug Guardian.Plug.LoadResource
end
...

And that seemed to do the trick.

Thanks all, for your help

mihaimartalogu

mihaimartalogu

Late to the party, but I use the same scenario, and I just managed to make it work after a bit of pain.

I had to:

  1. Set allowed_algos to [“RS256”]
    Authorization API signs JWTs as RS256 when HS256 is selected - Auth0 Community
  2. Set the issuer to exactly what the JWT says (i.e. including the leading “https://” and the trailing “/”). Check the “iss” field of your token on https://jwt.io/
  3. Use the public key (found under Auth0 → → Settings → Advanced Settings → Certificates → Signing Certificate), passed through JOSE.JWK.from_pem/1 as Guardian’s secret_key

Note that, as mentioned in %FunctionClauseError{arity: 1, function: :jose_jwk, module: Guardian} · Issue #291 · ueberauth/guardian · GitHub, you can’t call JOSE.JWK.from_pem/1 from config.exs, so I had to move that call into the application start/2 function:

# (in config.exs)
...
config :guardian, Guardian,
  ...
  secret_key_pem: "-----BEGIN CERTIFICATE-----..."
  ...

# (in <app>/lib/<app-name>.ex)
def start(_type, _args) do
  guardian_env = Application.get_env(:guardian, Guardian)
  secret_key = guardian_env |> Keyword.get(:secret_key_pem) |> JOSE.JWK.from_pem
  new_guardian_env = guardian_env |> Keyword.put(:secret_key, secret_key)
  Application.put_env(:guardian, Guardian, new_guardian_env)

Hope this helps

arcseldon

arcseldon

This blog details how the OP performed the same JWT Verification of Auth0 access token. Code also provided.

https://madebymany.com/stories/how-we-built-passwordless-authentication-with-auth0-and-elixir-phoenix

— All posts loaded —

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
jaybe78
Hello, I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter). The diffic...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
widianto
I think I’ve found a small improvement I could contribute to &lt;%= web_namespace %&gt;.CoreComponents (installer/templates/phx_web/compo...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews