Merge pull request #2740 from internetee/add-birthdate-verification

Added birthday ident verification
This commit is contained in:
Timo Võhmar 2025-01-31 17:50:55 +02:00 committed by GitHub
commit 3289851340
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 56 additions and 24 deletions

View file

@ -14,10 +14,11 @@ module Eeid
# POST /eeid/webhooks/identification_requests
def create
return render_unauthorized unless ip_whitelisted?
return render_invalid_signature unless valid_hmac_signature?(request.headers['X-HMAC-Signature'])
contact = Contact.find_by_code(permitted_params[:reference])
poi = catch_poi
return render_invalid_signature unless valid_hmac_signature?(contact.ident_type, request.headers['X-HMAC-Signature'])
poi = catch_poi(contact)
verify_contact(contact)
inform_registrar(contact, poi)
render json: { status: 'success' }, status: :ok
@ -39,8 +40,8 @@ module Eeid
render json: { error: 'Invalid HMAC signature' }, status: :unauthorized
end
def valid_hmac_signature?(hmac_signature)
secret = ENV['ident_service_client_secret']
def valid_hmac_signature?(ident_type, hmac_signature)
secret = ENV["#{ident_type}_ident_service_client_secret"]
computed_signature = OpenSSL::HMAC.hexdigest('SHA256', secret, request.raw_post)
ActiveSupport::SecurityUtils.secure_compare(computed_signature, hmac_signature)
end
@ -55,8 +56,8 @@ module Eeid
end
end
def catch_poi
ident_service = Eeid::IdentificationService.new
def catch_poi(contact)
ident_service = Eeid::IdentificationService.new(contact.ident_type)
response = ident_service.get_proof_of_identity(permitted_params[:identification_request_id])
raise StandardError, response[:error] if response[:error].present?

View file

@ -136,7 +136,7 @@ module Repp
desc 'Get proof of identity pdf file for a contact'
def download_poi
authorize! :verify, Epp::Contact
ident_service = Eeid::IdentificationService.new
ident_service = Eeid::IdentificationService.new(@contact.ident_type)
response = ident_service.get_proof_of_identity(@contact.verification_id)
send_data response[:data], filename: "proof_of_identity_#{@contact.verification_id}.pdf",

View file

@ -1,4 +1,7 @@
module Actions
# The ContactVerify class is responsible for handling the verification process
# for a contact, including creating identification requests and updating the
# contact's verification status.
class ContactVerify
attr_reader :contact
@ -7,10 +10,7 @@ module Actions
end
def call
if contact.verified_at.present?
contact.errors.add(:base, :verification_exists)
return
end
return false unless %w[priv birthday].include? contact.ident_type
create_identification_request
@ -22,7 +22,7 @@ module Actions
private
def create_identification_request
ident_service = Eeid::IdentificationService.new
ident_service = Eeid::IdentificationService.new(contact.ident_type)
response = ident_service.create_identification_request(request_payload)
ContactMailer.identification_requested(contact: contact, link: response['link']).deliver_now
rescue Eeid::IdentError => e
@ -31,6 +31,25 @@ module Actions
end
def request_payload
if contact.ident_type == 'birthday'
birthday_payload
else
default_payload
end
end
def birthday_payload
{
claims_required: [
{ type: 'birthdate', value: contact.ident },
{ type: 'name', value: contact.name },
{ type: 'country', value: contact.ident_country_code }
],
reference: contact.code
}
end
def default_payload
{
claims_required: [{
type: 'sub',
@ -41,7 +60,11 @@ module Actions
end
def commit
@contact.update(ident_request_sent_at: Time.zone.now)
@contact.update(
ident_request_sent_at: Time.zone.now,
verified_at: nil,
verification_id: nil
)
end
end
end

View file

@ -3,11 +3,11 @@
module Eeid
# This class handles identification services.
class IdentificationService < Base
CLIENT_ID = ENV['ident_service_client_id']
CLIENT_SECRET = ENV['ident_service_client_secret']
def initialize
super(CLIENT_ID, CLIENT_SECRET)
def initialize(ident_type = 'priv')
super(
ENV["#{ident_type}_ident_service_client_id"],
ENV["#{ident_type}_ident_service_client_secret"]
)
end
def create_identification_request(request_params)

View file

@ -261,5 +261,7 @@ whitelist_companies:
- '87654321'
eeid_base_url: 'http://eid.test'
ident_service_client_id: 123
ident_service_client_secret: 321
priv_ident_service_client_id: 123
priv_ident_service_client_secret: 321
birthday_ident_service_client_id: 456
birthday_ident_service_client_secret: 654

View file

@ -4,7 +4,7 @@ class Eeid::IdentificationRequestsWebhookTest < ActionDispatch::IntegrationTest
setup do
@contact = contacts(:john)
@secret = 'valid_secret'
ENV['ident_service_client_secret'] = @secret
ENV['priv_ident_service_client_secret'] = @secret
payload = {
identification_request_id: '123',
reference: @contact.code

View file

@ -66,13 +66,19 @@ class ReppV1ContactsVerifyTest < ActionDispatch::IntegrationTest
assert_emails 0
end
def test_does_not_verify_already_verified_contact
def test_reverify_already_verified_contact
@contact.update!(verified_at: Time.zone.now - 1.day)
post "/repp/v1/contacts/verify/#{@contact.code}", headers: @auth_headers
json = JSON.parse(response.body, symbolize_names: true)
assert_response :bad_request
assert_equal 'Contact already verified', json[:message]
assert_response :ok
assert_equal 1000, json[:code]
assert_equal 'Command completed successfully', json[:message]
contact = Contact.find_by(code: json[:data][:contact][:code])
assert contact.present?
assert contact.ident_request_sent_at
assert_nil contact.verified_at
end
def test_returns_error_response_if_throttled