diff --git a/.env.example b/.env.example index 2a7808848..1085cee63 100644 --- a/.env.example +++ b/.env.example @@ -63,3 +63,6 @@ S3_ACCESS_KEY_ID=your_s3_access_key_id_here S3_SECRET_ACCESS_KEY=your_s3_secret_access_key_here S3_BUCKET=your_s3_bucket_name_here S3_ENDPOINT=https://.r2.cloudflarestorage.com + +# Revocation key for token revocation +HKA_REVOCATION_KEY=your_hka_revocation_key_here \ No newline at end of file diff --git a/app/controllers/api/internal/revocations_controller.rb b/app/controllers/api/internal/revocations_controller.rb index c42f06e84..ebbeeb36a 100644 --- a/app/controllers/api/internal/revocations_controller.rb +++ b/app/controllers/api/internal/revocations_controller.rb @@ -1,26 +1,52 @@ module Api module Internal class RevocationsController < Api::Internal::ApplicationController + REGULAR_KEY_REGEX = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i + ADMIN_KEY_REGEX = /\Ahka_[0-9a-f]{64}\z/ + def create token = params[:token] return head 400 unless token.present? - admin_api_key = AdminApiKey.active.find_by(token:) - - return render json: { success: false } unless admin_api_key.present? + key, user = revocable_key_and_owner(token) - admin_api_key.revoke! + return render json: { success: false } unless key.present? - user = admin_api_key.user + revoke_key!(key) render json: { success: true, owner_email: user.email_addresses.first&.email, - key_name: admin_api_key.name + key_name: key.name }.compact_blank end + private + + def revocable_key_and_owner(token) + if token.match?(ADMIN_KEY_REGEX) + key = AdminApiKey.active.find_by(token:) + return [ key, key&.user ] + end + + if token.match?(REGULAR_KEY_REGEX) + key = ApiKey.find_by(token:) + return [ key, key&.user ] + end + + [ nil, nil ] + end + + def revoke_key!(key) + return key.revoke! if key.is_a?(AdminApiKey) + + key.update!( + token: SecureRandom.uuid_v4, + name: "#{key.name}_revoked_#{SecureRandom.hex(8)}" + ) + end + private def authenticate! res = authenticate_with_http_token do |token, _| ActiveSupport::SecurityUtils.secure_compare(token, ENV["HKA_REVOCATION_KEY"])