Rename OIDC strategy from :rauthy to :oidc, update callback path

- Rename AshAuthentication strategy from :oidc :rauthy to :oidc :oidc;
  generated actions are now register_with_oidc / sign_in_with_oidc.
- Update config keys (:rauthy → :oidc) in dev.exs and runtime.exs.
- Update default_redirect_uri to /auth/user/oidc/callback everywhere.
- Rename Mv.Accounts helper functions accordingly.
- Update Mv.Secrets, AuthController, link_oidc_account_live and all tests.
- Update docker-compose.prod.yml, .env.example, README and docs.

IMPORTANT: OIDC providers must be updated to use the new redirect URI
/auth/user/oidc/callback instead of /auth/user/rauthy/callback.
This commit is contained in:
Moritz 2026-02-24 10:34:36 +01:00
parent c637b6b84f
commit 339d37937a
Signed by: moritz
GPG key ID: 1020A035E5DD0824
25 changed files with 134 additions and 135 deletions

View file

@ -254,7 +254,7 @@ defmodule MvWeb.AuthControllerTest do
end
# OIDC/Rauthy error handling tests
describe "handle_rauthy_failure/2" do
describe "handle_oidc_failure/2" do
test "Assent.ServerUnreachableError redirects to sign-in with error flash", %{
conn: authenticated_conn
} do
@ -266,7 +266,7 @@ defmodule MvWeb.AuthControllerTest do
reason: %Mint.TransportError{reason: :econnrefused}
}
conn = MvWeb.AuthController.failure(conn, {:rauthy, :callback}, error)
conn = MvWeb.AuthController.failure(conn, {:oidc, :callback}, error)
assert redirected_to(conn) == ~p"/sign-in"
@ -288,7 +288,7 @@ defmodule MvWeb.AuthControllerTest do
}
}
conn = MvWeb.AuthController.failure(conn, {:rauthy, :callback}, error)
conn = MvWeb.AuthController.failure(conn, {:oidc, :callback}, error)
assert redirected_to(conn) == ~p"/sign-in"
@ -302,7 +302,7 @@ defmodule MvWeb.AuthControllerTest do
conn = build_unauthenticated_conn(authenticated_conn)
unknown_reason = :oops
conn = MvWeb.AuthController.failure(conn, {:rauthy, :callback}, unknown_reason)
conn = MvWeb.AuthController.failure(conn, {:oidc, :callback}, unknown_reason)
assert redirected_to(conn) == ~p"/sign-in"
@ -326,7 +326,7 @@ defmodule MvWeb.AuthControllerTest do
log =
capture_log(fn ->
MvWeb.AuthController.failure(conn, {:rauthy, :callback}, error)
MvWeb.AuthController.failure(conn, {:oidc, :callback}, error)
end)
# Should log redacted URL (only scheme and host)
@ -352,17 +352,17 @@ defmodule MvWeb.AuthControllerTest do
log =
capture_log(fn ->
MvWeb.AuthController.failure(conn, {:rauthy, :callback}, error)
MvWeb.AuthController.failure(conn, {:oidc, :callback}, error)
end)
# Should log error type but not full error details
assert log =~ "Authentication failure"
assert log =~ "rauthy"
assert log =~ "oidc"
# Should not log full error struct with inspect
refute log =~ "Assent.InvalidResponseError"
end
test "does not log full reason for unknown rauthy errors", %{
test "does not log full reason for unknown OIDC errors", %{
conn: authenticated_conn
} do
conn = build_unauthenticated_conn(authenticated_conn)
@ -375,19 +375,19 @@ defmodule MvWeb.AuthControllerTest do
log =
capture_log(fn ->
MvWeb.AuthController.failure(conn, {:rauthy, :callback}, error_with_sensitive_data)
MvWeb.AuthController.failure(conn, {:oidc, :callback}, error_with_sensitive_data)
end)
# Should log error type but not full error details
assert log =~ "Authentication failure"
assert log =~ "rauthy"
assert log =~ "oidc"
# Should NOT log sensitive data
refute log =~ "secret_token_123"
refute log =~ "access_token=abc123"
refute log =~ "callback?access_token"
end
test "logs full reason for non-rauthy activities (password auth)", %{
test "logs full reason for non-OIDC activities (password auth)", %{
conn: authenticated_conn
} do
conn = build_unauthenticated_conn(authenticated_conn)
@ -401,7 +401,7 @@ defmodule MvWeb.AuthControllerTest do
MvWeb.AuthController.failure(conn, {:password, :sign_in}, reason)
end)
# For non-rauthy activities, full reason is safe to log
# For non-OIDC activities, full reason is safe to log
assert log =~ "Authentication failure"
assert log =~ "password"
assert log =~ "AuthenticationFailed"

View file

@ -23,7 +23,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Call register action
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -38,7 +38,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Verify user can be found by oidc_id
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -74,7 +74,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Register (upsert) with new email
{:ok, updated_user} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: updated_user_info,
oauth_tokens: %{}
@ -107,7 +107,7 @@ defmodule MvWeb.OidcE2EFlowTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -146,7 +146,7 @@ defmodule MvWeb.OidcE2EFlowTest do
}
{:error, %Ash.Error.Invalid{errors: errors}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -185,7 +185,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Step 5: User can now sign in via OIDC
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -222,7 +222,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Collision detected
{:error, %Ash.Error.Invalid{}} =
Mv.Accounts.create_register_with_rauthy(%{
Mv.Accounts.create_register_with_oidc(%{
user_info: user_info,
oauth_tokens: %{}
})
@ -279,7 +279,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Collision detected
{:error, %Ash.Error.Invalid{}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -333,7 +333,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Sign-in should fail (no matching oidc_id)
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -357,7 +357,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Registration should trigger password requirement
{:error, %Ash.Error.Invalid{errors: errors}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -389,7 +389,7 @@ defmodule MvWeb.OidcE2EFlowTest do
# Should trigger hard error (not PasswordVerificationRequired)
{:error, %Ash.Error.Invalid{errors: errors}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -431,7 +431,7 @@ defmodule MvWeb.OidcE2EFlowTest do
}
{:error, %Ash.Error.Invalid{errors: errors}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -453,7 +453,7 @@ defmodule MvWeb.OidcE2EFlowTest do
}
{:error, %Ash.Error.Invalid{errors: errors}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -472,7 +472,7 @@ defmodule MvWeb.OidcE2EFlowTest do
}
{:error, %Ash.Error.Invalid{errors: errors}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}

View file

@ -28,7 +28,7 @@ defmodule MvWeb.OidcEmailUpdateTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
@ -70,7 +70,7 @@ defmodule MvWeb.OidcEmailUpdateTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
@ -135,7 +135,7 @@ defmodule MvWeb.OidcEmailUpdateTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
@ -190,7 +190,7 @@ defmodule MvWeb.OidcEmailUpdateTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
@ -234,7 +234,7 @@ defmodule MvWeb.OidcEmailUpdateTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
@ -271,7 +271,7 @@ defmodule MvWeb.OidcEmailUpdateTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}

View file

@ -24,11 +24,11 @@ defmodule MvWeb.OidcIntegrationTest do
"preferred_username" => "existing@example.com"
}
# Test sign_in_with_rauthy action directly
# Test sign_in_with_oidc action directly
system_actor = Mv.Helpers.SystemActor.get_system_actor()
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -48,17 +48,17 @@ defmodule MvWeb.OidcIntegrationTest do
assert found_user.oidc_id == "existing_oidc_123"
end
test "new OIDC user gets created via register_with_rauthy" do
test "new OIDC user gets created via register_with_oidc" do
# Simulate OIDC callback for completely new user
user_info = %{
"sub" => "brand_new_oidc_456",
"preferred_username" => "newuser@example.com"
}
# Test register_with_rauthy action
# Test register_with_oidc action
system_actor = Mv.Helpers.SystemActor.get_system_actor()
case Mv.Accounts.create_register_with_rauthy(
case Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -78,7 +78,7 @@ defmodule MvWeb.OidcIntegrationTest do
describe "OIDC sign-in security tests" do
@tag :test_proposal
test "sign_in_with_rauthy does NOT match user with only email (no oidc_id)" do
test "sign_in_with_oidc does NOT match user with only email (no oidc_id)" do
# SECURITY TEST: Ensure password-only users cannot be accessed via OIDC
# Create a password-only user (no oidc_id)
_password_user =
@ -98,7 +98,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -123,7 +123,7 @@ defmodule MvWeb.OidcIntegrationTest do
end
@tag :test_proposal
test "sign_in_with_rauthy only matches when oidc_id matches" do
test "sign_in_with_oidc only matches when oidc_id matches" do
# Create user with specific OIDC ID
user =
create_test_user(%{
@ -140,7 +140,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: correct_user_info,
oauth_tokens: %{}
@ -164,7 +164,7 @@ defmodule MvWeb.OidcIntegrationTest do
}
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: wrong_user_info,
oauth_tokens: %{}
@ -189,7 +189,7 @@ defmodule MvWeb.OidcIntegrationTest do
end
@tag :test_proposal
test "sign_in_with_rauthy does not match user with empty string oidc_id" do
test "sign_in_with_oidc does not match user with empty string oidc_id" do
# Edge case: empty string should be treated like nil
_user =
create_test_user(%{
@ -205,7 +205,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
result =
Mv.Accounts.read_sign_in_with_rauthy(
Mv.Accounts.read_sign_in_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -248,7 +248,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -284,7 +284,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -308,7 +308,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -338,7 +338,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, user} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -360,7 +360,7 @@ defmodule MvWeb.OidcIntegrationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, user} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}

View file

@ -32,7 +32,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -70,7 +70,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
{:error, %Ash.Error.Invalid{errors: errors}} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -167,7 +167,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -201,7 +201,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
# This should work via upsert
{:ok, updated_user} =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -308,7 +308,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{}
@ -380,7 +380,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(%{
Mv.Accounts.create_register_with_oidc(%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
})
@ -421,7 +421,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
@ -459,7 +459,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
@ -507,7 +507,7 @@ defmodule MvWeb.OidcPasswordLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(
Mv.Accounts.create_register_with_oidc(
%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}

View file

@ -45,7 +45,7 @@ defmodule MvWeb.OidcPasswordlessLinkingTest do
# Now OIDC sign-in should work
result =
Mv.Accounts.User
|> Ash.Query.for_read(:sign_in_with_rauthy, %{
|> Ash.Query.for_read(:sign_in_with_oidc, %{
user_info: %{
"sub" => "auto_link_oidc_123",
"preferred_username" => "invited@example.com"
@ -79,7 +79,7 @@ defmodule MvWeb.OidcPasswordlessLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(%{
Mv.Accounts.create_register_with_oidc(%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
})
@ -119,7 +119,7 @@ defmodule MvWeb.OidcPasswordlessLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(%{
Mv.Accounts.create_register_with_oidc(%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
})
@ -165,7 +165,7 @@ defmodule MvWeb.OidcPasswordlessLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(%{
Mv.Accounts.create_register_with_oidc(%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
})
@ -200,7 +200,7 @@ defmodule MvWeb.OidcPasswordlessLinkingTest do
}
result =
Mv.Accounts.create_register_with_rauthy(%{
Mv.Accounts.create_register_with_oidc(%{
user_info: user_info,
oauth_tokens: %{"access_token" => "test_token"}
})

View file

@ -89,7 +89,7 @@ defmodule MvWeb.ProfileNavigationTest do
user =
Mv.Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{
|> Ash.Changeset.for_create(:register_with_oidc, %{
user_info: user_info,
oauth_tokens: oauth_tokens
})
@ -140,7 +140,7 @@ defmodule MvWeb.ProfileNavigationTest do
oidc_user =
Mv.Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{
|> Ash.Changeset.for_create(:register_with_oidc, %{
user_info: user_info,
oauth_tokens: oauth_tokens
})