Failing to register on successful Google OAuth2.0 roundtrip

I am getting this error:

2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]** (exit) an exception was raised:
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]    ** (Ash.Error.Unknown) Unknown Error
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]Context: resolving data on perform Knowb.Accounts.User.register_with_google
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]* Context: resolving data on perform Knowb.Accounts.User.register_with_google
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]** (ArgumentError) No identity found for Knowb.Accounts.User called :email
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (ash 2.15.17) lib/ash/actions/create/create.ex:334: anonymous fn/11 in Ash.Actions.Create.as_requests/5
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (ash 2.15.17) lib/ash/engine/request.ex:1111: Ash.Engine.Request.do_try_resolve_local/4
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (ash 2.15.17) lib/ash/engine/request.ex:284: Ash.Engine.Request.do_next/1
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (ash 2.15.17) lib/ash/engine/request.ex:213: Ash.Engine.Request.next/1
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (ash 2.15.17) lib/ash/engine/engine.ex:712: Ash.Engine.advance_request/2
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (ash 2.15.17) lib/ash/engine/engine.ex:637: Ash.Engine.fully_advance_request/2
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (ash 2.15.17) lib/ash/engine/engine.ex:578: Ash.Engine.do_run_iteration/2
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]  (elixir 1.14.2) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (ash 2.15.17) lib/ash/actions/create/create.ex:334: anonymous fn/11 in Ash.Actions.Create.as_requests/5
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (ash 2.15.17) lib/ash/engine/request.ex:1111: Ash.Engine.Request.do_try_resolve_local/4
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (ash 2.15.17) lib/ash/engine/request.ex:284: Ash.Engine.Request.do_next/1
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (ash 2.15.17) lib/ash/engine/request.ex:213: Ash.Engine.Request.next/1
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (ash 2.15.17) lib/ash/engine/engine.ex:712: Ash.Engine.advance_request/2
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (ash 2.15.17) lib/ash/engine/engine.ex:637: Ash.Engine.fully_advance_request/2
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (ash 2.15.17) lib/ash/engine/engine.ex:578: Ash.Engine.do_run_iteration/2
2023-10-14T20:12:04Z app[e2866441be71d8] arn [info]        (elixir 1.14.2) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3

The User resource with the OAuth strategy is like this:

defmodule Knowb.Accounts.User do
  use Ash.Resource,
    data_layer: AshPostgres.DataLayer,
    extensions: [AshAuthentication]

  attributes do
    uuid_primary_key :id
    attribute :email, :ci_string, allow_nil?: false
  end

  actions do
    create :register_with_google do
      argument :user_info, :map, allow_nil?: false
      argument :oauth_tokens, :map, allow_nil?: false
      upsert? true
      upsert_identity :email

      change AshAuthentication.GenerateTokenChange

      change fn changeset, _ctx ->
        IO.inspect(changeset, label: "changeset")
        user_info = Ash.Changeset.get_argument(changeset, :user_info)
        IO.inspect(user_info, label: "user info")

        changeset
        |> Ash.Changeset.change_attribute(:email, user_info["email"])
      end
    end
  end

  authentication do
    api Knowb.Accounts

    strategies do
      oauth2 :google do
        # identity_resource Knowb.Accounts.Identity
        client_id Knowb.GoogleAuthSecrets
        client_secret Knowb.GoogleAuthSecrets
        redirect_uri Knowb.GoogleAuthSecrets
        site Knowb.GoogleAuthSecrets

        authorize_url "https://accounts.google.com/o/oauth2/auth"
        token_url "https://accounts.google.com/o/oauth2/token"
        user_url "https://www.googleapis.com/oauth2/v1/userinfo"

        authorization_params(
          scope:
            "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
          prompt: "select_account"
        )
      end
    end
  end

  postgres do
    table "users"
    repo Knowb.Repo
  end

  identities do
    identity :unique_email, [:email]
  end
end

I will say that I find the identities stuff a bit opaque so I may very well have missed something.

I think there are still places where this is messed up in the guide. upsert_identity should point at the name of an identity. The identity on your resource is called :unique_email

So you’d want to set upsert_identity :unique_email. We should improve that error message to list the available identities.

2 Likes

@AstonJ no Solved marking in ash-questions or troubleshooting? Not seeing it.

1 Like

Added :023:

2 Likes