Guardian, Google JWT token and `sign_in` function

Hi people,

I have a Phoenix website which uses Ueberauth and Guardian to authenticate users against Google SSO.

This is my config:

config :my_app, MyApp.Guardian,
  allowed_algos: ["RS256"],
  secret_key: %{
    "kid" => "5edd9782d820403ee8518c4aabb2b9fe310cac12",
    "e" => "AQAB",
    "kty" => "RSA",
    "alg" => "RS256",
    "n" =>
      "8leZQXh6eEjqv200Aot-ARc53fhnVex0bvPVoFAAOEuHmoR9HNqe4VUCCFX5qQ4uhTRrfpIoW-f4rZtY1gpt_4wUtNhS5-PQiSvCnljtIxCxgbW-gYKxsck8Xl-SMBYD1q4msIHbEZCE6AU_vFIgT5PjrUTo8O5YNFHpscsGDz1ZWeDTyRtf3UwTFm9p_dqSFIhyLzMo2H0BqWaowuAZeJnq0VIJxIrwjFqLj2rbBWkMxALui2uewerDrJIQQNgDqQiO8iClIbBmFxxDan5l89gHomb8HNVduIGZ3ahu18l94jQmhyVN8QQ8uNFoxfz2IfaZ3iwQL_xDtZHZtQLSUw",
    "use" => "sig"
  }

In particular the JKWS info come from here: https://www.googleapis.com/oauth2/v1/certs (I know, it’s regularly rotated, etc. For now this is not an issue).

The challenge phase is fine, I receive the Google token, at this point I verify that it is legit (it’s fun how in tutorials people skips this super important part, anyway). I can successfully do this with the following command:

{:ok, info} = MyApp.Guardian.decode_and_verify(token)

So, in order to verify the tokens everything is ok.

My problems happens when I try to use MyApp.Guardian.Plug.sign_in(email) that is the suggested way to use the Plug. I have this error:

no function clause matching in :jose_jwk_kty_rsa.sign/3

I have the feeling that I am just feeding the config with a public key info (which by definintion can only verify encrypted payloads), and since the sign_in function generates a token for the information I want to propagate, it needs a different configuration. But at this point I am lost about what would be the correct configuration … :confused:

This is a standard html pages website, and no API is involved: with APIs I could just reuse the token and verify it on each endpoint (at the very least).

Thanks in advance.

Ok, I leave this here for anyone who will eventually misunderstand Guardian like I did.

My understanding is that there was no bug in my implementation; the point is that I implemented only the logic to verify the google jwt token. In order to sign in (using MyApp.Guardian.Plug.sign_in) I must provide a proper specific implementation for it, with proper config (I refactored a bit the names):

config :my_app, MyApp.GoogleGuardian,
  allowed_algos: ["RS256"],
  secret_key: %{
    "kid" => "5edd9782d820403ee8518c4aabb2b9fe310cac12",
    "e" => "AQAB",
    "kty" => "RSA",
    "alg" => "RS256",
    "n" =>
      "8leZQXh6eEjqv200Aot-ARc53fhnVex0bvPVoFAAOEuHmoR9HNqe4VUCCFX5qQ4uhTRrfpIoW-f4rZtY1gpt_4wUtNhS5-PQiSvCnljtIxCxgbW-gYKxsck8Xl-SMBYD1q4msIHbEZCE6AU_vFIgT5PjrUTo8O5YNFHpscsGDz1ZWeDTyRtf3UwTFm9p_dqSFIhyLzMo2H0BqWaowuAZeJnq0VIJxIrwjFqLj2rbBWkMxALui2uewerDrJIQQNgDqQiO8iClIbBmFxxDan5l89gHomb8HNVduIGZ3ahu18l94jQmhyVN8QQ8uNFoxfz2IfaZ3iwQL_xDtZHZtQLSUw",
    "use" => "sig"
  }

config :my_app, MyApp.Guardian,
  issuer: "MyApp",
  secret_key: "my secret"

So when I have to validate the Google JWT token, i can do MyApp.GoogleGuardian.decode_and_verify(token), and MyApp.Guardian.Plug.sign_in(user) to generate a application-specific JWT.

Hope this might help avoiding my same mistake.

2 Likes

Thanks for answering! And I agree that Guardian can be confusing, I use it since forever and am confused by it from time to time.

You probably posted code that you use in a pipeline though, sign_in would need conn as the first argument and you will want the result - new_conn = MyApp.Guardian.Plug.sign_in(conn, user) instead of MyApp.Guardian.Plug.sign_in(user).

Yes, you are right, it was c&p from the controller, so the conn object is available :wink: