feat: rename OIDC strategy, fix sidebar, UI improvements closes #271 #444

Merged
moritz merged 12 commits from feat/ux_polishment into main 2026-02-24 13:05:11 +01:00
25 changed files with 134 additions and 135 deletions
Showing only changes of commit 339d37937a - Show all commits

View file

@ -22,8 +22,8 @@ ASSOCIATION_NAME="Sportsclub XYZ"
# These have defaults in docker-compose.prod.yml, only override if needed # These have defaults in docker-compose.prod.yml, only override if needed
# OIDC_CLIENT_ID=mv # OIDC_CLIENT_ID=mv
# OIDC_BASE_URL=http://localhost:8080/auth/v1 # OIDC_BASE_URL=http://localhost:8080/auth/v1
# OIDC_REDIRECT_URI=http://localhost:4001/auth/user/rauthy/callback # OIDC_REDIRECT_URI=http://localhost:4001/auth/user/oidc/callback
# OIDC_CLIENT_SECRET=your-rauthy-client-secret # OIDC_CLIENT_SECRET=your-oidc-client-secret
# Optional: OIDC group → Admin role sync (e.g. Authentik groups from profile scope) # Optional: OIDC group → Admin role sync (e.g. Authentik groups from profile scope)
# If OIDC_ADMIN_GROUP_NAME is set, users in that group get Admin role on registration/sign-in. # If OIDC_ADMIN_GROUP_NAME is set, users in that group get Admin role on registration/sign-in.

View file

@ -142,7 +142,7 @@ Mila uses OIDC for Single Sign-On. In development, a local **Rauthy** instance i
3. Login with "admin@localhost" and password from `BOOTSTRAP_ADMIN_PASSWORD_PLAIN` in docker-compose.yml 3. Login with "admin@localhost" and password from `BOOTSTRAP_ADMIN_PASSWORD_PLAIN` in docker-compose.yml
4. add client from the admin panel 4. add client from the admin panel
- Client ID: mv - Client ID: mv
- redirect uris: http://localhost:4000/auth/user/rauthy/callback - redirect uris: http://localhost:4000/auth/user/oidc/callback
- Authorization Flows: authorization_code - Authorization Flows: authorization_code
- allowed origins: http://localhost:4000 - allowed origins: http://localhost:4000
- access/id token algortihm: RS256 (EDDSA did not work for me, found just few infos in the ashauthentication docs) - access/id token algortihm: RS256 (EDDSA did not work for me, found just few infos in the ashauthentication docs)
@ -155,11 +155,11 @@ Now you can log in to Mila via OIDC!
Mila works with any OIDC-compliant provider. The internal strategy is named `:rauthy`, but this is just a name — it works with any provider. Mila works with any OIDC-compliant provider. The internal strategy is named `:rauthy`, but this is just a name — it works with any provider.
**Important:** The redirect URI must always end with `/auth/user/rauthy/callback`. **Important:** The redirect URI must always end with `/auth/user/oidc/callback`.
Example for Authentik: Example for Authentik:
1. Create an OAuth2/OpenID Provider in Authentik 1. Create an OAuth2/OpenID Provider in Authentik
2. Set the redirect URI to: `https://your-domain.com/auth/user/rauthy/callback` 2. Set the redirect URI to: `https://your-domain.com/auth/user/oidc/callback`
3. Configure environment variables: 3. Configure environment variables:
```bash ```bash
DOMAIN=your-domain.com # or PHX_HOST=your-domain.com DOMAIN=your-domain.com # or PHX_HOST=your-domain.com
@ -168,7 +168,7 @@ Example for Authentik:
OIDC_CLIENT_SECRET=your-client-secret # or use OIDC_CLIENT_SECRET_FILE OIDC_CLIENT_SECRET=your-client-secret # or use OIDC_CLIENT_SECRET_FILE
``` ```
The `OIDC_REDIRECT_URI` is auto-generated as `https://{DOMAIN}/auth/user/rauthy/callback` if not explicitly set. The `OIDC_REDIRECT_URI` is auto-generated as `https://{DOMAIN}/auth/user/oidc/callback` if not explicitly set.
## ⚙️ Configuration ## ⚙️ Configuration
@ -238,7 +238,7 @@ For testing the production Docker build locally:
# OIDC_CLIENT_ID=mv # OIDC_CLIENT_ID=mv
# OIDC_BASE_URL=http://localhost:8080/auth/v1 # OIDC_BASE_URL=http://localhost:8080/auth/v1
# OIDC_CLIENT_SECRET=<from-your-oidc-provider> # OIDC_CLIENT_SECRET=<from-your-oidc-provider>
# OIDC_REDIRECT_URI is auto-generated as https://{DOMAIN}/auth/user/rauthy/callback # OIDC_REDIRECT_URI is auto-generated as https://{DOMAIN}/auth/user/oidc/callback
# Alternative: Use _FILE variables for Docker secrets (takes priority over regular vars): # Alternative: Use _FILE variables for Docker secrets (takes priority over regular vars):
# SECRET_KEY_BASE_FILE=/run/secrets/secret_key_base # SECRET_KEY_BASE_FILE=/run/secrets/secret_key_base

View file

@ -93,11 +93,11 @@ config :mv, :secret_key_base, "ryn7D6ssmIHQFWIks2sFiTGATgwwAR1+3bN8p7fy6qVtB8qnx
# Signing Secret for Authentication # Signing Secret for Authentication
config :mv, :token_signing_secret, "IwUwi65TrEeExwBXXFPGm2I7889NsL" config :mv, :token_signing_secret, "IwUwi65TrEeExwBXXFPGm2I7889NsL"
config :mv, :rauthy, config :mv, :oidc,
client_id: "mv", client_id: "mv",
base_url: "http://localhost:8080/auth/v1", base_url: "http://localhost:8080/auth/v1",
client_secret: System.get_env("OIDC_CLIENT_SECRET"), client_secret: System.get_env("OIDC_CLIENT_SECRET"),
redirect_uri: "http://localhost:4000/auth/user/rauthy/callback" redirect_uri: "http://localhost:4000/auth/user/oidc/callback"
# AshAuthentication development configuration # AshAuthentication development configuration
config :mv, :session_identifier, :jti config :mv, :session_identifier, :jti

View file

@ -129,8 +129,7 @@ if config_env() == :prod do
config :mv, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") config :mv, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
# OIDC configuration (works with any OIDC provider: Authentik, Rauthy, Keycloak, etc.) # OIDC configuration (works with any OIDC provider: Authentik, Rauthy, Keycloak, etc.)
# Note: The strategy is named :rauthy internally, but works with any OIDC provider. # The redirect_uri callback path is /auth/user/oidc/callback.
# The redirect_uri callback path is always /auth/user/rauthy/callback regardless of provider.
# #
# Supports OIDC_CLIENT_SECRET or OIDC_CLIENT_SECRET_FILE for Docker secrets. # Supports OIDC_CLIENT_SECRET or OIDC_CLIENT_SECRET_FILE for Docker secrets.
# OIDC_CLIENT_SECRET is required only if OIDC is being used (indicated by explicit OIDC env vars). # OIDC_CLIENT_SECRET is required only if OIDC is being used (indicated by explicit OIDC env vars).
@ -150,9 +149,9 @@ if config_env() == :prod do
# Build redirect_uri: use OIDC_REDIRECT_URI if set, otherwise build from host. # Build redirect_uri: use OIDC_REDIRECT_URI if set, otherwise build from host.
# Uses HTTPS since production runs behind TLS termination. # Uses HTTPS since production runs behind TLS termination.
default_redirect_uri = "https://#{host}/auth/user/rauthy/callback" default_redirect_uri = "https://#{host}/auth/user/oidc/callback"
config :mv, :rauthy, config :mv, :oidc,
client_id: oidc_client_id || "mv", client_id: oidc_client_id || "mv",
base_url: oidc_base_url || "http://localhost:8080/auth/v1", base_url: oidc_base_url || "http://localhost:8080/auth/v1",
client_secret: client_secret, client_secret: client_secret,

View file

@ -18,11 +18,11 @@ services:
PHX_HOST: "${PHX_HOST:-localhost}" PHX_HOST: "${PHX_HOST:-localhost}"
PORT: "4001" PORT: "4001"
PHX_SERVER: "true" PHX_SERVER: "true"
# Rauthy OIDC config - use host.docker.internal to reach host services # OIDC config - use host.docker.internal to reach host services
OIDC_CLIENT_ID: "mv" OIDC_CLIENT_ID: "mv"
OIDC_BASE_URL: "http://host.docker.internal:8080/auth/v1" OIDC_BASE_URL: "http://host.docker.internal:8080/auth/v1"
OIDC_CLIENT_SECRET_FILE: "/run/secrets/oidc_client_secret" OIDC_CLIENT_SECRET_FILE: "/run/secrets/oidc_client_secret"
OIDC_REDIRECT_URI: "http://localhost:4001/auth/user/rauthy/callback" OIDC_REDIRECT_URI: "http://localhost:4001/auth/user/oidc/callback"
secrets: secrets:
- db_password - db_password
- secret_key_base - secret_key_base

View file

@ -39,8 +39,8 @@
### Where It Runs ### Where It Runs
1. Registration: register_with_rauthy after_action calls OidcRoleSync. 1. Registration: register_with_oidc after_action calls OidcRoleSync.
2. Sign-in: sign_in_with_rauthy prepare after_action calls OidcRoleSync for each user. 2. Sign-in: sign_in_with_oidc prepare after_action calls OidcRoleSync for each user.
### Internal Action ### Internal Action

View file

@ -886,7 +886,7 @@ just regen-migrations <name>
**Checklist:** **Checklist:**
1. ✅ Rauthy running: `docker compose ps` 1. ✅ Rauthy running: `docker compose ps`
2. ✅ Client created in Rauthy admin panel 2. ✅ Client created in Rauthy admin panel
3. ✅ Redirect URI matches exactly: `http://localhost:4000/auth/user/rauthy/callback` 3. ✅ Redirect URI matches exactly: `http://localhost:4000/auth/user/oidc/callback`
4. ✅ OIDC_CLIENT_SECRET in .env 4. ✅ OIDC_CLIENT_SECRET in .env
5. ✅ App restarted after .env update 5. ✅ App restarted after .env update

View file

@ -501,8 +501,8 @@ Since this is a **Phoenix LiveView** application with **Ash Framework**, we have
|--------|-------|---------|------|---------|----------| |--------|-------|---------|------|---------|----------|
| `GET` | `/auth/user/password/sign_in` | Show password login form | 🔓 | - | HTML form | | `GET` | `/auth/user/password/sign_in` | Show password login form | 🔓 | - | HTML form |
| `POST` | `/auth/user/password/sign_in` | Submit password login | 🔓 | `{email, password}` | Redirect + session cookie | | `POST` | `/auth/user/password/sign_in` | Submit password login | 🔓 | `{email, password}` | Redirect + session cookie |
| `GET` | `/auth/user/rauthy` | Initiate OIDC flow | 🔓 | - | Redirect to Rauthy | | `GET` | `/auth/user/oidc` | Initiate OIDC flow | 🔓 | - | Redirect to Rauthy |
| `GET` | `/auth/user/rauthy/callback` | Handle OIDC callback | 🔓 | `{code, state}` | Redirect + session cookie | | `GET` | `/auth/user/oidc/callback` | Handle OIDC callback | 🔓 | `{code, state}` | Redirect + session cookie |
| `POST` | `/auth/user/sign_out` | Sign out user | 🔐 | - | Redirect to login | | `POST` | `/auth/user/sign_out` | Sign out user | 🔐 | - | Redirect to login |
| `GET` | `/auth/link-oidc-account` | OIDC account linking (password verification) | 🔓 | - | LiveView form | ✅ Implemented | | `GET` | `/auth/link-oidc-account` | OIDC account linking (password verification) | 🔓 | - | LiveView form | ✅ Implemented |
| `GET` | `/auth/user/password/reset` | Show password reset form | 🔓 | - | HTML form | | `GET` | `/auth/user/password/reset` | Show password reset form | 🔓 | - | HTML form |

View file

@ -10,10 +10,10 @@ This feature implements secure account linking between password-based accounts a
#### 1. Security Fix: `lib/accounts/user.ex` #### 1. Security Fix: `lib/accounts/user.ex`
**Change**: The `sign_in_with_rauthy` action now filters by `oidc_id` instead of `email`. **Change**: The `sign_in_with_oidc` action now filters by `oidc_id` instead of `email`.
```elixir ```elixir
read :sign_in_with_rauthy do read :sign_in_with_oidc do
argument :user_info, :map, allow_nil?: false argument :user_info, :map, allow_nil?: false
argument :oauth_tokens, :map, allow_nil?: false argument :oauth_tokens, :map, allow_nil?: false
prepare AshAuthentication.Strategy.OAuth2.SignInPreparation prepare AshAuthentication.Strategy.OAuth2.SignInPreparation

View file

@ -9,7 +9,7 @@ defmodule Mv.Accounts do
## Public API ## Public API
The domain exposes these main actions: The domain exposes these main actions:
- User CRUD: `create_user/1`, `list_users/0`, `update_user/2`, `destroy_user/1` - User CRUD: `create_user/1`, `list_users/0`, `update_user/2`, `destroy_user/1`
- Authentication: `create_register_with_rauthy/1`, `read_sign_in_with_rauthy/1` - Authentication: `create_register_with_oidc/1`, `read_sign_in_with_oidc/1`
""" """
use Ash.Domain, use Ash.Domain,
extensions: [AshAdmin.Domain, AshPhoenix] extensions: [AshAdmin.Domain, AshPhoenix]
@ -24,8 +24,8 @@ defmodule Mv.Accounts do
define :list_users, action: :read define :list_users, action: :read
define :update_user, action: :update_user define :update_user, action: :update_user
define :destroy_user, action: :destroy define :destroy_user, action: :destroy
define :create_register_with_rauthy, action: :register_with_rauthy define :create_register_with_oidc, action: :register_with_oidc
define :read_sign_in_with_rauthy, action: :sign_in_with_rauthy define :read_sign_in_with_oidc, action: :sign_in_with_oidc
end end
resource Mv.Accounts.Token resource Mv.Accounts.Token

View file

@ -28,7 +28,7 @@ defmodule Mv.Accounts.User do
@doc """ @doc """
AshAuthentication specific: Defines the strategies we want to use for authentication. AshAuthentication specific: Defines the strategies we want to use for authentication.
Currently password and SSO with Rauthy as OIDC provider Currently password and SSO via OIDC (supports any provider: Authentik, Rauthy, Keycloak, etc.)
""" """
authentication do authentication do
session_identifier Application.compile_env!(:mv, :session_identifier) session_identifier Application.compile_env!(:mv, :session_identifier)
@ -52,7 +52,7 @@ defmodule Mv.Accounts.User do
end end
strategies do strategies do
oidc :rauthy do oidc :oidc do
client_id Mv.Secrets client_id Mv.Secrets
base_url Mv.Secrets base_url Mv.Secrets
redirect_uri Mv.Secrets redirect_uri Mv.Secrets
@ -88,7 +88,7 @@ defmodule Mv.Accounts.User do
# Always use one of these explicit create actions instead: # Always use one of these explicit create actions instead:
# - :create_user (for manual user creation with optional member link) # - :create_user (for manual user creation with optional member link)
# - :register_with_password (for password-based registration) # - :register_with_password (for password-based registration)
# - :register_with_rauthy (for OIDC-based registration) # - :register_with_oidc (for OIDC-based registration)
defaults [:read] defaults [:read]
destroy :destroy do destroy :destroy do
@ -267,7 +267,7 @@ defmodule Mv.Accounts.User do
prepare AshAuthentication.Preparations.FilterBySubject prepare AshAuthentication.Preparations.FilterBySubject
end end
read :sign_in_with_rauthy do read :sign_in_with_oidc do
# Single record expected; required for AshAuthentication OAuth2 strategy (returns list of 0 or 1). # Single record expected; required for AshAuthentication OAuth2 strategy (returns list of 0 or 1).
get? true get? true
argument :user_info, :map, allow_nil?: false argument :user_info, :map, allow_nil?: false
@ -302,7 +302,7 @@ defmodule Mv.Accounts.User do
end) end)
end end
create :register_with_rauthy do create :register_with_oidc do
argument :user_info, :map, allow_nil?: false argument :user_info, :map, allow_nil?: false
argument :oauth_tokens, :map, allow_nil?: false argument :oauth_tokens, :map, allow_nil?: false
upsert? true upsert? true

View file

@ -7,7 +7,7 @@ defmodule Mv.Secrets do
particularly for OIDC (Rauthy) authentication. particularly for OIDC (Rauthy) authentication.
## Configuration Source ## Configuration Source
Secrets are read from the `:rauthy` key in the application configuration, Secrets are read from the `:oidc` key in the application configuration,
which is typically set in `config/runtime.exs` from environment variables: which is typically set in `config/runtime.exs` from environment variables:
- `OIDC_CLIENT_ID` - `OIDC_CLIENT_ID`
- `OIDC_CLIENT_SECRET` - `OIDC_CLIENT_SECRET`
@ -21,7 +21,7 @@ defmodule Mv.Secrets do
use AshAuthentication.Secret use AshAuthentication.Secret
def secret_for( def secret_for(
[:authentication, :strategies, :rauthy, :client_id], [:authentication, :strategies, :oidc, :client_id],
Mv.Accounts.User, Mv.Accounts.User,
_opts, _opts,
_meth _meth
@ -30,7 +30,7 @@ defmodule Mv.Secrets do
end end
def secret_for( def secret_for(
[:authentication, :strategies, :rauthy, :redirect_uri], [:authentication, :strategies, :oidc, :redirect_uri],
Mv.Accounts.User, Mv.Accounts.User,
_opts, _opts,
_meth _meth
@ -39,7 +39,7 @@ defmodule Mv.Secrets do
end end
def secret_for( def secret_for(
[:authentication, :strategies, :rauthy, :client_secret], [:authentication, :strategies, :oidc, :client_secret],
Mv.Accounts.User, Mv.Accounts.User,
_opts, _opts,
_meth _meth
@ -48,7 +48,7 @@ defmodule Mv.Secrets do
end end
def secret_for( def secret_for(
[:authentication, :strategies, :rauthy, :base_url], [:authentication, :strategies, :oidc, :base_url],
Mv.Accounts.User, Mv.Accounts.User,
_opts, _opts,
_meth _meth
@ -58,7 +58,7 @@ defmodule Mv.Secrets do
defp get_config(key) do defp get_config(key) do
:mv :mv
|> Application.fetch_env!(:rauthy) |> Application.fetch_env!(:oidc)
|> Keyword.fetch!(key) |> Keyword.fetch!(key)
|> then(&{:ok, &1}) |> then(&{:ok, &1})
end end

View file

@ -48,8 +48,8 @@ defmodule MvWeb.AuthController do
log_failure_safely(activity, reason) log_failure_safely(activity, reason)
case {activity, reason} do case {activity, reason} do
{{:rauthy, _action}, reason} -> {{:oidc, _action}, reason} ->
handle_rauthy_failure(conn, reason) handle_oidc_failure(conn, reason)
{_, %AshAuthentication.Errors.AuthenticationFailed{caused_by: caused_by}} -> {_, %AshAuthentication.Errors.AuthenticationFailed{caused_by: caused_by}} ->
handle_authentication_failed(conn, caused_by) handle_authentication_failed(conn, caused_by)
@ -61,8 +61,8 @@ defmodule MvWeb.AuthController do
end end
end end
# Log authentication failures safely, avoiding sensitive data for {:rauthy, _} activities # Log authentication failures safely, avoiding sensitive data for {:oidc, _} activities
defp log_failure_safely({:rauthy, _action} = activity, reason) do defp log_failure_safely({:oidc, _action} = activity, reason) do
# For Assent errors, use safe_assent_meta to avoid logging tokens/URLs with query params # For Assent errors, use safe_assent_meta to avoid logging tokens/URLs with query params
case reason do case reason do
%Assent.ServerUnreachableError{} = err -> %Assent.ServerUnreachableError{} = err ->
@ -76,7 +76,7 @@ defmodule MvWeb.AuthController do
Logger.warning(message) Logger.warning(message)
_ -> _ ->
# For other rauthy errors, log only error type, not full details # For other OIDC errors, log only error type, not full details
error_type = get_error_type(reason) error_type = get_error_type(reason)
Logger.warning( Logger.warning(
@ -86,7 +86,7 @@ defmodule MvWeb.AuthController do
end end
defp log_failure_safely(activity, reason) do defp log_failure_safely(activity, reason) do
# For non-rauthy activities, safe to log full reason # For non-OIDC activities, safe to log full reason
Logger.warning( Logger.warning(
"Authentication failure - Activity: #{inspect(activity)}, Reason: #{inspect(reason)}" "Authentication failure - Activity: #{inspect(activity)}, Reason: #{inspect(reason)}"
) )
@ -119,12 +119,12 @@ defmodule MvWeb.AuthController do
if Enum.empty?(parts), do: "", else: " - " <> Enum.join(parts, ", ") if Enum.empty?(parts), do: "", else: " - " <> Enum.join(parts, ", ")
end end
# Handle all Rauthy (OIDC) authentication failures # Handle all OIDC authentication failures
defp handle_rauthy_failure(conn, %Ash.Error.Invalid{errors: errors}) do defp handle_oidc_failure(conn, %Ash.Error.Invalid{errors: errors}) do
handle_oidc_email_collision(conn, errors) handle_oidc_email_collision(conn, errors)
end end
defp handle_rauthy_failure(conn, %AshAuthentication.Errors.AuthenticationFailed{ defp handle_oidc_failure(conn, %AshAuthentication.Errors.AuthenticationFailed{
caused_by: caused_by caused_by: caused_by
}) do }) do
case caused_by do case caused_by do
@ -139,7 +139,7 @@ defmodule MvWeb.AuthController do
end end
# Handle Assent server unreachable errors (network/connectivity issues) # Handle Assent server unreachable errors (network/connectivity issues)
defp handle_rauthy_failure(conn, %Assent.ServerUnreachableError{} = _err) do defp handle_oidc_failure(conn, %Assent.ServerUnreachableError{} = _err) do
# Logging already done safely in failure/3 via log_failure_safely/2 # Logging already done safely in failure/3 via log_failure_safely/2
# No need to log again here to avoid duplicate logs # No need to log again here to avoid duplicate logs
@ -152,7 +152,7 @@ defmodule MvWeb.AuthController do
end end
# Handle Assent invalid response errors (configuration or malformed responses) # Handle Assent invalid response errors (configuration or malformed responses)
defp handle_rauthy_failure(conn, %Assent.InvalidResponseError{} = _err) do defp handle_oidc_failure(conn, %Assent.InvalidResponseError{} = _err) do
# Logging already done safely in failure/3 via log_failure_safely/2 # Logging already done safely in failure/3 via log_failure_safely/2
# No need to log again here to avoid duplicate logs # No need to log again here to avoid duplicate logs
@ -165,7 +165,7 @@ defmodule MvWeb.AuthController do
end end
# Catch-all clause for any other error types # Catch-all clause for any other error types
defp handle_rauthy_failure(conn, _reason) do defp handle_oidc_failure(conn, _reason) do
# Logging already done safely in failure/3 via log_failure_safely/2 # Logging already done safely in failure/3 via log_failure_safely/2
# No need to log again here to avoid duplicate logs # No need to log again here to avoid duplicate logs

View file

@ -84,7 +84,7 @@ defmodule MvWeb.LinkOidcAccountLive do
:info, :info,
dgettext("auth", "Account activated! Redirecting to complete sign-in...") dgettext("auth", "Account activated! Redirecting to complete sign-in...")
) )
|> Phoenix.LiveView.redirect(to: ~p"/auth/user/rauthy") |> Phoenix.LiveView.redirect(to: ~p"/auth/user/oidc")
{:error, error} -> {:error, error} ->
Logger.warning( Logger.warning(
@ -223,7 +223,7 @@ defmodule MvWeb.LinkOidcAccountLive do
"Your OIDC account has been successfully linked! Redirecting to complete sign-in..." "Your OIDC account has been successfully linked! Redirecting to complete sign-in..."
) )
) )
|> Phoenix.LiveView.redirect(to: ~p"/auth/user/rauthy")} |> Phoenix.LiveView.redirect(to: ~p"/auth/user/oidc")}
{:error, error} -> {:error, error} ->
Logger.warning( Logger.warning(

View file

@ -103,13 +103,13 @@ defmodule Mv.Accounts.UserAuthenticationTest do
"preferred_username" => "oidc.user@example.com" "preferred_username" => "oidc.user@example.com"
} }
# Use sign_in_with_rauthy to find user by oidc_id # Use sign_in_with_oidc to find user by oidc_id
# Note: This test will FAIL until we implement the security fix # Note: This test will FAIL until we implement the security fix
# that changes the filter from email to oidc_id # that changes the filter from email to oidc_id
system_actor = Mv.Helpers.SystemActor.get_system_actor() system_actor = Mv.Helpers.SystemActor.get_system_actor()
result = result =
Mv.Accounts.read_sign_in_with_rauthy( Mv.Accounts.read_sign_in_with_oidc(
%{ %{
user_info: user_info, user_info: user_info,
oauth_tokens: %{} oauth_tokens: %{}
@ -145,11 +145,11 @@ defmodule Mv.Accounts.UserAuthenticationTest do
"preferred_username" => "newuser@example.com" "preferred_username" => "newuser@example.com"
} }
# Should create via register_with_rauthy # Should create via register_with_oidc
system_actor = Mv.Helpers.SystemActor.get_system_actor() system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, new_user} = {:ok, new_user} =
Mv.Accounts.create_register_with_rauthy( Mv.Accounts.create_register_with_oidc(
%{ %{
user_info: user_info, user_info: user_info,
oauth_tokens: %{} oauth_tokens: %{}
@ -196,8 +196,8 @@ defmodule Mv.Accounts.UserAuthenticationTest do
describe "Mixed authentication scenarios" do describe "Mixed authentication scenarios" do
@tag :test_proposal @tag :test_proposal
test "user with oidc_id cannot be found by email-only query in sign_in_with_rauthy" do test "user with oidc_id cannot be found by email-only query in sign_in_with_oidc" do
# This test verifies the security fix: sign_in_with_rauthy should NOT # This test verifies the security fix: sign_in_with_oidc should NOT
# match users by email, only by oidc_id # match users by email, only by oidc_id
_user = _user =
@ -218,7 +218,7 @@ defmodule Mv.Accounts.UserAuthenticationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor() system_actor = Mv.Helpers.SystemActor.get_system_actor()
result = result =
Mv.Accounts.read_sign_in_with_rauthy( Mv.Accounts.read_sign_in_with_oidc(
%{ %{
user_info: user_info, user_info: user_info,
oauth_tokens: %{} oauth_tokens: %{}
@ -238,12 +238,12 @@ defmodule Mv.Accounts.UserAuthenticationTest do
:ok :ok
other -> other ->
flunk("sign_in_with_rauthy should not match by email alone, got: #{inspect(other)}") flunk("sign_in_with_oidc should not match by email alone, got: #{inspect(other)}")
end end
end end
@tag :test_proposal @tag :test_proposal
test "password user (oidc_id=nil) is not found by sign_in_with_rauthy" do test "password user (oidc_id=nil) is not found by sign_in_with_oidc" do
# Create a password-only user # Create a password-only user
_user = _user =
create_test_user(%{ create_test_user(%{
@ -262,7 +262,7 @@ defmodule Mv.Accounts.UserAuthenticationTest do
system_actor = Mv.Helpers.SystemActor.get_system_actor() system_actor = Mv.Helpers.SystemActor.get_system_actor()
result = result =
Mv.Accounts.read_sign_in_with_rauthy( Mv.Accounts.read_sign_in_with_oidc(
%{ %{
user_info: user_info, user_info: user_info,
oauth_tokens: %{} oauth_tokens: %{}
@ -283,7 +283,7 @@ defmodule Mv.Accounts.UserAuthenticationTest do
other -> other ->
flunk( flunk(
"Password-only user should not be found by sign_in_with_rauthy, got: #{inspect(other)}" "Password-only user should not be found by sign_in_with_oidc, got: #{inspect(other)}"
) )
end end
end end

View file

@ -206,7 +206,7 @@ defmodule Mv.Accounts.UserEmailSyncTest do
# Simulate OIDC registration # Simulate OIDC registration
{:ok, user} = {:ok, user} =
Mv.Accounts.User Mv.Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{ |> Ash.Changeset.for_create(:register_with_oidc, %{
user_info: user_info, user_info: user_info,
oauth_tokens: oauth_tokens oauth_tokens: oauth_tokens
}) })

View file

@ -283,7 +283,7 @@ defmodule Mv.Accounts.UserPoliciesTest do
assert user_with_role.role.name == "Mitglied" assert user_with_role.role.name == "Mitglied"
end end
test "register_with_rauthy works without actor via AshAuthentication bypass" do test "register_with_oidc works without actor via AshAuthentication bypass" do
# Test that AshAuthentication bypass allows OIDC registration without actor # Test that AshAuthentication bypass allows OIDC registration without actor
user_info = %{ user_info = %{
"sub" => "oidc_sub_#{System.unique_integer([:positive])}", "sub" => "oidc_sub_#{System.unique_integer([:positive])}",
@ -294,7 +294,7 @@ defmodule Mv.Accounts.UserPoliciesTest do
changeset = changeset =
Accounts.User Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{ |> Ash.Changeset.for_create(:register_with_oidc, %{
user_info: user_info, user_info: user_info,
oauth_tokens: oauth_tokens oauth_tokens: oauth_tokens
}) })
@ -306,7 +306,7 @@ defmodule Mv.Accounts.UserPoliciesTest do
assert user.oidc_id == user_info["sub"] assert user.oidc_id == user_info["sub"]
end end
test "sign_in_with_rauthy works without actor via AshAuthentication bypass" do test "sign_in_with_oidc works without actor via AshAuthentication bypass" do
# First create a user with OIDC ID (using system_actor for setup) # First create a user with OIDC ID (using system_actor for setup)
system_actor = Mv.Helpers.SystemActor.get_system_actor() system_actor = Mv.Helpers.SystemActor.get_system_actor()
@ -319,16 +319,16 @@ defmodule Mv.Accounts.UserPoliciesTest do
{:ok, user} = {:ok, user} =
Accounts.User Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{ |> Ash.Changeset.for_create(:register_with_oidc, %{
user_info: user_info_create, user_info: user_info_create,
oauth_tokens: oauth_tokens oauth_tokens: oauth_tokens
}) })
|> Ash.create(actor: system_actor) |> Ash.create(actor: system_actor)
# Now test sign_in_with_rauthy without actor (should work via AshAuthentication bypass) # Now test sign_in_with_oidc without actor (should work via AshAuthentication bypass)
query = query =
Accounts.User Accounts.User
|> Ash.Query.for_read(:sign_in_with_rauthy, %{ |> Ash.Query.for_read(:sign_in_with_oidc, %{
user_info: user_info_create, user_info: user_info_create,
oauth_tokens: oauth_tokens oauth_tokens: oauth_tokens
}) })

View file

@ -104,8 +104,8 @@ defmodule Mv.OidcRoleSyncTest do
end end
end end
# B3: Role sync after registration is implemented via after_action in register_with_rauthy. # B3: Role sync after registration is implemented via after_action in register_with_oidc.
# Full integration tests (create_register_with_rauthy + assert role) are skipped: when the # Full integration tests (create_register_with_oidc + assert role) are skipped: when the
# nested Ash.update! runs inside the create's after_action, authorization may evaluate in # nested Ash.update! runs inside the create's after_action, authorization may evaluate in
# the create context so set_role_from_oidc_sync bypass does not apply. Sync logic is covered # the create context so set_role_from_oidc_sync bypass does not apply. Sync logic is covered
# by the apply_admin_role_from_user_info tests above. B4 sign-in sync will also use that. # by the apply_admin_role_from_user_info tests above. B4 sign-in sync will also use that.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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