UI for oidc account linking
This commit is contained in:
parent
87e54cb13f
commit
527657d37b
3 changed files with 256 additions and 15 deletions
|
|
@ -24,28 +24,104 @@ defmodule MvWeb.AuthController do
|
|||
end
|
||||
|
||||
def failure(conn, activity, reason) do
|
||||
Logger.error(%{conn: conn, reason: reason})
|
||||
# Log the error for debugging
|
||||
Logger.warning(
|
||||
"Authentication failure - Activity: #{inspect(activity)}, Reason: #{inspect(reason)}"
|
||||
)
|
||||
|
||||
message =
|
||||
case {activity, reason} do
|
||||
{_,
|
||||
%AshAuthentication.Errors.AuthenticationFailed{
|
||||
caused_by: %Ash.Error.Forbidden{
|
||||
errors: [%AshAuthentication.Errors.CannotConfirmUnconfirmedUser{}]
|
||||
}
|
||||
}} ->
|
||||
case {activity, reason} do
|
||||
# OIDC registration with existing email requires password verification (direct error)
|
||||
{{:rauthy, :register}, %Ash.Error.Invalid{errors: errors}} ->
|
||||
handle_oidc_email_collision(conn, errors)
|
||||
|
||||
# OIDC registration with existing email (wrapped in AuthenticationFailed)
|
||||
{{:rauthy, :register},
|
||||
%AshAuthentication.Errors.AuthenticationFailed{
|
||||
caused_by: %Ash.Error.Invalid{errors: errors}
|
||||
}} ->
|
||||
handle_oidc_email_collision(conn, errors)
|
||||
|
||||
# OIDC sign-in failure (wrapped)
|
||||
{{:rauthy, :sign_in}, %AshAuthentication.Errors.AuthenticationFailed{caused_by: caused_by}} ->
|
||||
# Check if it's actually a registration issue
|
||||
case caused_by do
|
||||
%Ash.Error.Invalid{errors: errors} ->
|
||||
handle_oidc_email_collision(conn, errors)
|
||||
|
||||
_ ->
|
||||
# Real sign-in failure
|
||||
conn
|
||||
|> put_flash(:error, gettext("Unable to sign in with OIDC. Please try again."))
|
||||
|> redirect(to: ~p"/sign-in")
|
||||
end
|
||||
|
||||
# OIDC callback failure (can be either sign-in or registration)
|
||||
{{:rauthy, :callback}, %AshAuthentication.Errors.AuthenticationFailed{caused_by: caused_by}} ->
|
||||
case caused_by do
|
||||
%Ash.Error.Invalid{errors: errors} ->
|
||||
handle_oidc_email_collision(conn, errors)
|
||||
|
||||
_ ->
|
||||
conn
|
||||
|> put_flash(:error, gettext("Unable to authenticate with OIDC. Please try again."))
|
||||
|> redirect(to: ~p"/sign-in")
|
||||
end
|
||||
|
||||
{_,
|
||||
%AshAuthentication.Errors.AuthenticationFailed{
|
||||
caused_by: %Ash.Error.Forbidden{
|
||||
errors: [%AshAuthentication.Errors.CannotConfirmUnconfirmedUser{}]
|
||||
}
|
||||
}} ->
|
||||
message =
|
||||
gettext("""
|
||||
You have already signed in another way, but have not confirmed your account.
|
||||
You can confirm your account using the link we sent to you, or by resetting your password.
|
||||
""")
|
||||
|
||||
_ ->
|
||||
gettext("Incorrect email or password")
|
||||
end
|
||||
conn
|
||||
|> put_flash(:error, message)
|
||||
|> redirect(to: ~p"/sign-in")
|
||||
|
||||
conn
|
||||
|> put_flash(:error, message)
|
||||
|> redirect(to: ~p"/sign-in")
|
||||
_ ->
|
||||
message = gettext("Incorrect email or password")
|
||||
|
||||
conn
|
||||
|> put_flash(:error, message)
|
||||
|> redirect(to: ~p"/sign-in")
|
||||
end
|
||||
end
|
||||
|
||||
# Handle OIDC email collision - user needs to verify password
|
||||
defp handle_oidc_email_collision(conn, errors) do
|
||||
password_verification_error =
|
||||
Enum.find(errors, fn err ->
|
||||
match?(%Mv.Accounts.User.Errors.PasswordVerificationRequired{}, err)
|
||||
end)
|
||||
|
||||
case password_verification_error do
|
||||
%Mv.Accounts.User.Errors.PasswordVerificationRequired{
|
||||
user_id: user_id,
|
||||
oidc_user_info: oidc_user_info
|
||||
} ->
|
||||
# Store the OIDC info in session for the linking flow
|
||||
conn
|
||||
|> put_session(:oidc_linking_user_id, user_id)
|
||||
|> put_session(:oidc_linking_user_info, oidc_user_info)
|
||||
|> put_flash(
|
||||
:info,
|
||||
gettext(
|
||||
"An account with this email already exists. Please verify your password to link your OIDC account."
|
||||
)
|
||||
)
|
||||
|> redirect(to: ~p"/auth/link-oidc-account")
|
||||
|
||||
_ ->
|
||||
# Other validation errors - show generic error
|
||||
conn
|
||||
|> put_flash(:error, gettext("Unable to sign in. Please try again."))
|
||||
|> redirect(to: ~p"/sign-in")
|
||||
end
|
||||
end
|
||||
|
||||
def sign_out(conn, _params) do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue