Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Google Sign in for mobile strategy #89

Open
sezaru opened this issue Jul 17, 2021 · 0 comments
Open

Google Sign in for mobile strategy #89

sezaru opened this issue Jul 17, 2021 · 0 comments

Comments

@sezaru
Copy link

sezaru commented Jul 17, 2021

Currently, assent has support for Google Sign in for the web, the client sends the code and scope and the strategy retrieves from google the JWT with the data.

This works fine for the web, but not so much for mobile apps where normally the client will retrieve the JWT (id token) directly and the server job is to validate it.

Since I need exactly this case, I created a new strategy for it, you can add it to Assent if you want, and also I would appreciate it if you can take a look and see if there is some flaw in the logic.

The strategy itself is very simple, you simply send the id_token to id and it will validate it.

defmodule Core.Identity.GoogleSignIn.Strategy do
  @moduledoc false

  alias Core.Identity.GoogleSignIn.JWTManager

  @behaviour Assent.Strategy

  @impl true
  def callback(_, params) do
    %{id_token: id_token} = params

    case JWTManager.verify_and_validate(id_token) do
      {:ok, user} -> {:ok, %{user: user}}
      {:error, _} -> {:error, :invalid_token}
    end
  end

  @impl true
  def authorize_url(_), do: throw("not implemented")
end

For validation, here are my modules:

defmodule Core.Identity.GoogleSignIn.JWTVerifyHook do
  @moduledoc false

  use Joken.Hooks

  @impl true
  def before_verify(_, {jwt, %Joken.Signer{}}) do
    with {:ok, %{"kid" => kid}} <- Joken.peek_header(jwt),
         {:ok, algorithm, key} <- GoogleCerts.fetch(kid) do
      {:cont, {jwt, Joken.Signer.create(algorithm, key)}}
    else
      _ -> {:halt, {:error, :no_signer}}
    end
  end
end
defmodule Core.Identity.GoogleSignIn.JWTManager do
  @moduledoc false

  alias Core.Identity.GoogleSignIn.JWTVerifyHook

  use Joken.Config, default_signer: nil

  add_hook(JWTVerifyHook)

  @iss "https://accounts.google.com"

  @impl true
  def token_config do
    default_claims(skip: [:aud, :iss])
    |> add_claim("iss", nil, fn iss -> iss == @iss end)
    |> add_claim("aud", nil, fn aud -> aud == aud() end)
  end

  defp aud do
    Application.fetch_env!(:core, :pow_assent)
       |> Keyword.fetch!(:providers)
       |> Keyword.fetch!(:google_sign_in)
       |> Keyword.fetch!(:client_id)
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant