diff --git a/elixir/apps/domain/lib/domain/auth/adapters/okta/jobs/sync_directory.ex b/elixir/apps/domain/lib/domain/auth/adapters/okta/jobs/sync_directory.ex index a8588a42e..6689a68e7 100644 --- a/elixir/apps/domain/lib/domain/auth/adapters/okta/jobs/sync_directory.ex +++ b/elixir/apps/domain/lib/domain/auth/adapters/okta/jobs/sync_directory.ex @@ -44,15 +44,15 @@ defmodule Domain.Auth.Adapters.Okta.Jobs.SyncDirectory do message = "#{error_code} => #{error_summary}" {:error, message, "Okta API returned #{status}: #{message}"} - # TODO: Okta API client needs to be updated to pull message from header - {:error, {401, ""}} -> + {:error, {401, error_map}} -> + user_message = inspect(error_map, pretty: true) message = "401 - Unauthorized" - {:error, message, message} + {:error, user_message, message} - # TODO: Okta API client needs to be updated to pull message from header - {:error, {403, ""}} -> + {:error, {403, error_map}} -> + user_message = inspect(error_map, pretty: true) message = "403 - Forbidden" - {:error, message, message} + {:error, user_message, message} {:error, :retry_later} -> message = "Okta API is temporarily unavailable" diff --git a/elixir/apps/domain/test/domain/auth/adapters/okta/jobs/sync_directory_test.exs b/elixir/apps/domain/test/domain/auth/adapters/okta/jobs/sync_directory_test.exs index 94dfcf4ee..88758c185 100644 --- a/elixir/apps/domain/test/domain/auth/adapters/okta/jobs/sync_directory_test.exs +++ b/elixir/apps/domain/test/domain/auth/adapters/okta/jobs/sync_directory_test.exs @@ -941,7 +941,7 @@ defmodule Domain.Auth.Adapters.Okta.Jobs.SyncDirectoryTest do cancel_bypass_expectations_check(bypass) end - test "sends email on failed directory sync", %{ + test "sends email on failed directory sync when errors are in body", %{ account: account, provider: provider, bypass: bypass @@ -986,5 +986,54 @@ defmodule Domain.Auth.Adapters.Okta.Jobs.SyncDirectoryTest do cancel_bypass_expectations_check(bypass) end + + test "sends email on failed directory sync when errors are in header", %{ + account: account, + provider: provider, + bypass: bypass + } do + actor = Fixtures.Actors.create_actor(type: :account_admin_user, account: account) + _identity = Fixtures.Auth.create_identity(account: account, actor: actor) + + # Okta returns 401 with error info in www-authenticate header + www_authenticate_header = + "Bearer authorization_uri=\"http://example.okta.com/oauth2/v1/authorize\", " <> + "realm=\"http://example.okta.com\", " <> + "scope=\"okta.groups.read\", " <> + "error=\"invalid_token\", " <> + "error_description=\"The token has expired.\", " <> + "resource=\"/api/v1/groups\"" + + for path <- [ + "api/v1/users", + "api/v1/groups" + ] do + Bypass.stub(bypass, "GET", path, fn conn -> + conn + |> Plug.Conn.put_resp_header("www-authenticate", www_authenticate_header) + |> Plug.Conn.send_resp(401, "") + end) + end + + {:ok, pid} = Task.Supervisor.start_link() + + provider + |> Ecto.Changeset.change(last_syncs_failed: 9) + |> Repo.update!() + + assert execute(%{task_supervisor: pid}) == :ok + + assert_email_sent(fn email -> + assert email.subject == "Firezone Identity Provider Sync Error" + assert email.text_body =~ "failed to sync 10 time(s)" + end) + + {:ok, pid} = Task.Supervisor.start_link() + assert execute(%{task_supervisor: pid}) == :ok + + refute_email_sent() + + cancel_bypass_expectations_check(bypass) + end end end