diff --git a/app/controllers/oidc_accounts_controller.rb b/app/controllers/oidc_accounts_controller.rb index 6e22a1c93..4e7c9275f 100644 --- a/app/controllers/oidc_accounts_controller.rb +++ b/app/controllers/oidc_accounts_controller.rb @@ -102,10 +102,12 @@ class OidcAccountsController < ApplicationController # Security: JIT users should NOT have password_digest set to prevent # chained authentication attacks where SSO users gain local login access # via password reset. + # Allow user to edit first_name and last_name from the form, but email comes from OIDC + user_params = params.fetch(:user, {}).permit(:first_name, :last_name) @user = User.new( email: email, - first_name: @pending_auth["first_name"], - last_name: @pending_auth["last_name"], + first_name: user_params[:first_name].presence || @pending_auth["first_name"], + last_name: user_params[:last_name].presence || @pending_auth["last_name"], skip_password_validation: true ) diff --git a/app/views/oidc_accounts/new_user.html.erb b/app/views/oidc_accounts/new_user.html.erb new file mode 100644 index 000000000..4656d4dba --- /dev/null +++ b/app/views/oidc_accounts/new_user.html.erb @@ -0,0 +1,37 @@ +<% + header_title t("oidc_accounts.new_user.title") +%> + +
+

<%= t("oidc_accounts.new_user.heading") %>

+

+ <%= t("oidc_accounts.new_user.description", provider: @pending_auth["provider"]) %> +

+
+ +<%= styled_form_with model: @user, url: create_user_oidc_account_path, class: "space-y-4", data: { turbo: false } do |form| %> +
+

<%= t("oidc_accounts.new_user.email_label") %>

+

<%= @pending_auth["email"] %>

+
+ + <%= form.text_field :first_name, + label: t("oidc_accounts.new_user.first_name_label"), + placeholder: t("oidc_accounts.new_user.first_name_placeholder"), + autofocus: true %> + + <%= form.text_field :last_name, + label: t("oidc_accounts.new_user.last_name_label"), + placeholder: t("oidc_accounts.new_user.last_name_placeholder") %> + + <%= form.submit t("oidc_accounts.new_user.submit") %> +<% end %> + +
+ <%= render DS::Link.new( + text: t("oidc_accounts.new_user.cancel"), + href: new_session_path, + variant: :default, + class: "font-medium text-sm text-primary hover:underline transition" + ) %> +
diff --git a/config/locales/views/oidc_accounts/en.yml b/config/locales/views/oidc_accounts/en.yml index d39572b2a..618baf7e2 100644 --- a/config/locales/views/oidc_accounts/en.yml +++ b/config/locales/views/oidc_accounts/en.yml @@ -3,3 +3,14 @@ en: oidc_accounts: link: account_creation_disabled: New account creation via single sign-on is disabled. Please contact an administrator to create your account. + new_user: + title: Complete Your Account + heading: Create Your Account + description: Please confirm your details to complete account creation with your %{provider} identity. + email_label: Email (from SSO provider) + first_name_label: First Name + first_name_placeholder: Enter your first name + last_name_label: Last Name + last_name_placeholder: Enter your last name + submit: Create Account + cancel: Cancel diff --git a/test/controllers/oidc_accounts_controller_test.rb b/test/controllers/oidc_accounts_controller_test.rb index 9cb283960..a26975176 100644 --- a/test/controllers/oidc_accounts_controller_test.rb +++ b/test/controllers/oidc_accounts_controller_test.rb @@ -98,6 +98,18 @@ class OidcAccountsControllerTest < ActionController::TestCase } end + test "should show new_user page when pending auth exists" do + session[:pending_oidc_auth] = new_user_auth + get :new_user + assert_response :success + end + + test "should redirect new_user to login when no pending auth" do + get :new_user + assert_redirected_to new_session_path + assert_equal "No pending OIDC authentication found", flash[:alert] + end + test "should show create account option for new user" do session[:pending_oidc_auth] = new_user_auth @@ -175,6 +187,34 @@ class OidcAccountsControllerTest < ActionController::TestCase assert_equal new_user_auth["uid"], oidc_identity.uid end + test "create_user uses form params for name when provided" do + session[:pending_oidc_auth] = new_user_auth + + assert_difference [ "User.count", "OidcIdentity.count" ], 1 do + post :create_user, params: { + user: { first_name: "Custom", last_name: "Name" } + } + end + + assert_redirected_to root_path + + new_user = User.find_by(email: new_user_auth["email"]) + assert_equal "Custom", new_user.first_name + assert_equal "Name", new_user.last_name + end + + test "create_user falls back to OIDC data when form params are blank" do + session[:pending_oidc_auth] = new_user_auth + + post :create_user, params: { + user: { first_name: "", last_name: "" } + } + + new_user = User.find_by(email: new_user_auth["email"]) + assert_equal new_user_auth["first_name"], new_user.first_name + assert_equal new_user_auth["last_name"], new_user.last_name + end + test "should create session after OIDC registration" do session[:pending_oidc_auth] = new_user_auth