Skip to content

Split Arkose::UserVerificationService into two services

Eugie Limpin requested to merge split_user_verification_service into master

This MR is the second of a multi-MR change to integrate Arkose Labs to the registration flow.

  1. Display Arkose Labs challenge in the registration form (instead of reCAPTCHA)
  2. Split Arkose::UserVerificationService into Arkose::TokenVerificationService and Arkose::RecordUserDataService 👈🏼 👈🏼 👈🏼 YOU ARE HERE
  3. Verify Arkose Labs session token before registration and record Arkose Labs user data after registration

What does this MR do and why?

Split Arkose::UserVerificationService into two services as follows:

  1. Arkose::TokenVerificationService - responsible for sending a request to Arkose Labs Verify API endpoint to perform verification of the session token passed from the frontend
  2. Arkose::RecordUserDataService - responsible for persisting the user's data from Arkose Labs into the database. Currently, data persisted are arkose_session (id), arkose_risk_band, arkose_global_score, arkose_custom_score.

Functionally, there is one minor difference between the resulting two services and Arkose::UserVerificationService. Previously, Arkose::UserVerificationService prevents the user from logging in when they are not deemed low_risk:

def execute
  ...
  response.allowlisted? || (response.challenge_solved? && response.low_risk?)
end

Now Arkose::TokenVerificationService just returns low_risk? value as part of the ServiceResponse.payload and delegates the decision whether to prevent the user from logging in to SessionsController:

# ee/app/services/arkose/token_verification_service.rb
def execute
  if response.allowlisted? || response.challenge_solved?
    ServiceResponse.success(payload: { low_risk: response.allowlisted? || response.low_risk? })
  else
    ServiceResponse.error(message: 'Captcha was not solved')
  end
end

# ee/app/controllers/ee/sessions_controller.rb
def verify_arkose_token(user)
  result = Arkose::TokenVerificationService.new(session_token: params[:arkose_labs_token], user: user).execute

  if result.success? && result.payload[:low_risk]
    # allow log in
  else
    # prevent log in
  end
end

This change is warranted since for registration flow we will allow the user to register regardless of their risk_score.

Why?

This refactor is needed so we can verify a session token and persist user data in two separate steps during registration. TokenVerificationService (step 1) will be executed before a user is created to ensure the CAPTCHA has been solved while RecordUserDataService (step 2) will be executed after the user is created.

Screenshots or screen recordings

Screenshots are required for UI changes, and strongly recommended for all other merge requests.

How to set up and validate locally

Numbered steps to set up and validate the change are strongly suggested.

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Eugie Limpin

Merge request reports

Loading