ueberauth / guardian

Elixir Authentication
MIT License
3.43k stars 382 forks source link

Can I verify a JWToken created by Auth0 ? #211

Closed alduro closed 7 years ago

alduro commented 7 years ago

Should I implement my own verify_module ?

config.ex

config :guardian, Guardian,
    allowed_algos: ["HS256"],
   verify_module: BlackMamba.JWTHelpers,
    issuer: System.get_env("AUTH0_DOMAIN"),
  #  ttl: { 7, :days },
    verify_issuer: true,
  #  secret_key: System.get_env("GUARDIAN_SECRET") || raise("Missing GUARDIAN_SECRET"),
    secret_key: System.get_env("AUTH0_CLIENT_SECRET") || raise("Missing AUTH0_CLIENT_SECRET"),
    serializer: BlackMamba.GuardianSerializer

router.ex

pipeline :graphql do
     plug GraphqlLogger
     plug Guardian.Plug.VerifyHeader, realm: "Bearer", key: System.get_env("AUTH0_CLIENT_SECRET")
#   plug Guardian.Plug.EnsureAuthenticated
     plug Guardian.Plug.LoadResource
     plug BlackMamba.Context
 end

verify module

defmodule BlackMamba.JWTHelpers do
  1   import Joken, except: [verify: 1]
  2   require Logger
  3
  4   def verify(jwt) do
  5     verify
  6       |> with_json_module(Poison)
  7       |> with_compact_token(jwt)
  8       |> Joken.verify
  9   end
 10
 11   @doc """
 12   use for verification via plug
 13   issuer should be our auth0 domain
 14   app_metadata must be present in id_token
 15   """
 16   def verify do
 17     Logger.debug "Verify called"
 18     %Joken.Token{}
 19        |> with_json_module(Poison)
 20        |> with_signer(hs256(config[:app_secret]))
 21        |> with_validation("aud", &(&1 == config[:app_id]))
 22        |> with_validation("exp", &(&1 > current_time))
 23        |> with_validation("iat", &(&1 <= current_time))
 24   end
hassox commented 7 years ago

not sure what you're trying to achieve. Also, why use your client secret as a key in the verify header? That is not the secret that will be used, it's just a location in the assigns (allowing multiple sign ins at the same time). Whatever 'key' you use on your verify header module you use, you need to use that always - EnsureAuthenticated and LoadResource - need the same key. Usually the 'key' you'd use there would be something like 'default', 'admin'. It's just a label to tell guardian which login you're talking about. It's good for things like impersonation or temporary heightened security

enilsen16 commented 7 years ago

I might be wrong but I think the idea is to use the token from auth0, rather than have guardian create it. Either way I am interested in this as well.

Right now I verify a correct response from auth0 and then have guardian create a separate token.

I added Auth0 login to the phoenix_guardian repo as an example. https://github.com/enilsen16/phoenix_guardian/tree/auth0

alduro commented 7 years ago

@enilsen16 yeah you are right. The token was created by Auth0 and I do need to use their secret key to decode it, get the sub, split it and loading the resource from Token. I cannot make it work yet.

@hassox yeah, key in VerifyHeader was an attempt to make it work with no luck. Just added my own verify_module but didn't work either.

enilsen16 commented 7 years ago

@alduro are you using @sntran's uberauth_auth0 package?

alduro commented 7 years ago

@enilsen16 ah no. Any sample to check ?

enilsen16 commented 7 years ago

Here's the repo for the package: https://github.com/sntran/ueberauth_auth0

The last two commits in my auth0 branch here are adding it to phoenix guardian.

alduro commented 7 years ago

I just checked it out. The problem is I'm also interested in some other Guardian features like LoadResource based on sub payload. Well I dunno, maybe I can implement my own Plug.

enilsen16 commented 7 years ago

I am using both(uberauth/guardian) and it seems to work just fine...

hassox commented 7 years ago

In order to use the auth0 as a token that you're going to trust as your applications token, I think you'd have to set your secret key to be the same signing secret that the auth0 token was signed with. At that point, when you receive the auth0 token you put it into the session/conn assigns the same way that the sign_in function does and it should all just work.

Just work might be a bit of a stretch though. Your token serializer will need to match whatever they put into the token, permissions likely won't work because I don't think that auto0 would have access to your bitmask and I'm not sure GuardianDb would work out of the box. For that to work it would need to have a jti specified in the JWT.

Personally I like to put a boundary between my system and another. If I were using auth0 I would treat that like a login action where I received that token and then generated one of my own based on it. That's probably just me though ;)

You can use Guardian to decode the token from auth0 provided you know the signing secret.

Guardian.decode_and_verify(jwt, %{secret: auth0_secret})
alduro commented 7 years ago

Thanks guys ! I will check this out and let you know how it went before closing it I guess.

alduro commented 7 years ago

No luck. I'd really appreciate any code sample applying directions above.

hassox commented 7 years ago

@alduro is your project public? I don't actually use auth0 but if I could see some code it might help me identify what you're trying to do.

alduro commented 7 years ago

@hassox no. I will create an small gist for sharing. Update: https://gist.github.com/alduro/bffc1f03a890b025f4abe66b1e27450f

alduro commented 7 years ago

Sorry, any clue ? @hassox

alduro commented 7 years ago

It was solved !

config.ex

config :guardian, Guardian,
 11   allowed_algos: ["HS256"],
 10   verify_module: Guardian.JWT,
  9   issuer: System.get_env("AUTH0_DOMAIN"),
  8   verify_issuer: false,
  7   secret_key: System.get_env("AUTH0_CLIENT_SECRET") |> Base.url_decode64 |> elem(1),
  6   serializer: App.GuardianSerializer

Serializer

def from_token("auth0|" <> id), do: {:ok, Repo.get(User, id)}

router.ex

 pipeline :graphql do
  2     plug GraphqlLogger
  1     plug Guardian.Plug.VerifyHeader, realm: "Bearer"
18      plug Guardian.Plug.EnsureAuthenticated
  1     plug Guardian.Plug.LoadResource
  2     plug App.Context
  3   end