chore: rotate oauth password if unconfirmed (#13878)
When a user signs up with an email they don't own and sets a password, that password remains valid even after the real owner later signs in via OAuth. This means the original registrant — who never proved ownership of the email — retains working credentials on the account. This change closes that gap by rotating the password to a random value whenever an unconfirmed user completes an OAuth sign-in. The check (`oauth_user_needs_password_reset?`) is evaluated before `skip_confirmation!` runs, since confirmation would flip `confirmed_at` and mask the condition. If the user was unconfirmed, the stored password is replaced with a secure random string that satisfies the password policy. This applies to both the web and mobile OAuth callback paths, as well as the sign-up path where the password is rotated before the reset token is generated. Users who lose access to password-based login as a side effect can recover through the standard "Forgot password" flow at any time. Since they've already proven email ownership via OAuth, this is a low-friction recovery path
This commit is contained in:
@@ -164,5 +164,21 @@ RSpec.describe 'DeviseOverrides::OmniauthCallbacksController', type: :request do
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
it 'resets password for an unconfirmed persisted user on OAuth login' do
|
||||
with_modified_env FRONTEND_URL: 'http://www.example.com' do
|
||||
user = create(:user, email: 'unconfirmed-oauth@example.com', skip_confirmation: false)
|
||||
original_password_digest = user.encrypted_password
|
||||
set_omniauth_config('unconfirmed-oauth@example.com')
|
||||
|
||||
get '/omniauth/google_oauth2/callback'
|
||||
expect(response).to redirect_to('http://www.example.com/auth/google_oauth2/callback')
|
||||
follow_redirect!
|
||||
|
||||
user.reload
|
||||
expect(user).to be_confirmed
|
||||
expect(user.encrypted_password).not_to eq(original_password_digest)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user