ueberauth / guardian

Elixir Authentication
MIT License
3.44k stars 381 forks source link

RS256 #485

Closed MeterSoft closed 6 years ago

MeterSoft commented 6 years ago

I tried to decode RS256 access code but it returns error Olist.Guardian.decode_and_verify(token) {:error, :invalid_token}

# config

config :olist, Olist.Guardian,
   issuer: "olist",
   secret_key: "3UpoE1SvErp2GKrS7fj+uWUWI05EoF0w/0YcE7cVDKjakTr7nKqxWRt61GkJsCZr",
   verify_module: Guardian.JWT,
   allowed_algos: ["RS256"]

defmodule Olist.Guardian do
  use Guardian, otp_app: :olist
end
pauldoerwald commented 6 years ago

I too am getting token errors. I have an RS256 token (generated by Auth0) which is happily accepted by https://jwt.io but that Guardian refuses to process. When I tried generating an RS256 key (by setting allowed_algos: ["RS256"] as @MeterSoft did above, Guardian responded with:

Interactive Elixir (1.6.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, t, fc} = Clockk.Guardian.encode_and_sign(%{name: "Paul", id: 1})                                                   
** (ErlangError) Erlang error: {:not_supported, [:RS256]}                                                                            
    (jose) src/jose_jwk_kty_oct.erl:191: :jose_jwk_kty_oct.jws_alg_to_digest_type/1                                                  
    (jose) src/jose_jwk_kty_oct.erl:122: :jose_jwk_kty_oct.sign/3
    (jose) src/jose_jws.erl:311: :jose_jws.sign/4
    (jose) src/jose_jwt.erl:171: :jose_jwt.sign/3
    (guardian) lib/guardian/token/jwt.ex:168: Guardian.Token.Jwt.create_token/3
    (guardian) lib/guardian.ex:754: Guardian.returning_tuple/1
    (guardian) lib/guardian.ex:581: Guardian.encode_and_sign/4

Could there be a bug here? Auth0 recommends using RS256 keys, but maybe I should use HS512, which Guardian accepts without complaint?

pauldoerwald commented 6 years ago

I just realized something: RS256 uses public keys, which explains why the secret key I have doesn't work... I need to use my Auth0 public key... I think. Maybe HS256/HS512 is the right approach...

pauldoerwald commented 6 years ago

As always happens, as soon as I start asking for help, I figure it out.

The problem above was how I was specifying the secret_key. It should be something more like:

config :clockk, Clockk.Guardian, allowed_algos: ["HS512"], issuer: "clockk.auth0.com", secret_key: fn -> "-----BEGIN CERTIFICATE----- certificate goes here. Ordinarily you would keep this in a file which you would load, but I'm putting it inline for simplicity. -----END CERTIFICATE----- " |> Kernel.||("") |> String.replace("\n", "\n") |> JOSE.JWT.from_pem end

With this secret_key, things start to work. However, because of the argument in https://github.com/ueberauth/guardian/issues/152 which points out that RSA keys are VERY slow and thus inappropriate for Bearer authorization, I'm switching to HS256 which works much more like what @MeterSoft above did.

So with that, I'm dropping my part of this issue, and I suggest that this is not an issue at all and should be closed.

yordis commented 6 years ago

@pauldoerwald thanks a lot for the research, I am happy that you figured it out.

@MeterSoft feel free to reopen it if you think this still an issue for you but please follow @pauldoerwald instructions first.

jaybe78 commented 2 weeks ago

@yordis Spent the whole day on this and I was able to make it work for HS256 but as for me whatever I do RS256 algo never works !

I've verified EVERYTHING!! If my implementation was incorrect, I guess I would not even be able to make it work for HS256 either, so I guess something must be wrong

for the record I tried to create a token uising

Messages.Authentication.Guardian.encode_and_sign(%{
        email: userPK })

it failed with

Erlang error: {:not_supported, [:RS256]}

I confirm that I've correctly my public key in my config

config :messages, Messages.Authentication.Guardian,
secret_key_file: "public.pem",
verify_module: Guardian.JWT,
allowed_algos: ["RS256"]

Just to make sure my public and private keys were correct, I used another lib to check (yajwt)

The following works without any issue

privateKey =
      JWT.Algorithm.RsaUtil.private_key(Fast64.decode64(System.get_env("OAUTH_PRIVATE_KEY")))
publicKey =
      JWT.Algorithm.RsaUtil.public_key(Fast64.decode64(System.get_env("OAUTH_PUBLIC_KEY")))

  jwt = JWT.sign(
      %{
        email: userPK,
        exp: DateTime.to_unix(DateTime.add(datetime, 3600, :minute)),
      },
      %{
        key: privateKey,
       alg: "RS256"
      }
    )

JWT.verify(jwt, %{key: publicKey, alg: "RS256"})