summaryrefslogtreecommitdiff
path: root/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/auth/otp/strategies/forti_token_cloud.rb')
-rw-r--r--lib/gitlab/auth/otp/strategies/forti_token_cloud.rb72
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb b/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb
new file mode 100644
index 00000000000..d7506eca242
--- /dev/null
+++ b/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Auth
+ module Otp
+ module Strategies
+ class FortiTokenCloud < Base
+ include Gitlab::Utils::StrongMemoize
+ BASE_API_URL = 'https://ftc.fortinet.com:9696/api/v1'
+
+ def validate(otp_code)
+ if access_token_create_response.created?
+ otp_verification_response = verify_otp(otp_code)
+
+ otp_verification_response.ok? ? success : error_from_response(otp_verification_response)
+ else
+ error_from_response(access_token_create_response)
+ end
+ end
+
+ private
+
+ # TODO: Cache the access token: https://gitlab.com/gitlab-org/gitlab/-/issues/292437
+ def access_token_create_response
+ # Returns '201 CREATED' on successful creation of a new access token.
+ strong_memoize(:access_token_create_response) do
+ post(
+ url: url('/login'),
+ body: {
+ client_id: ::Gitlab.config.forti_token_cloud.client_id,
+ client_secret: ::Gitlab.config.forti_token_cloud.client_secret
+ }.to_json
+ )
+ end
+ end
+
+ def access_token
+ Gitlab::Json.parse(access_token_create_response)['access_token']
+ end
+
+ def verify_otp(otp_code)
+ # Returns '200 OK' on successful verification.
+ # Uses the access token created via `access_token_create_response` as the auth token.
+ post(
+ url: url('/auth'),
+ headers: { 'Authorization': "Bearer #{access_token}" },
+ body: {
+ username: user.username,
+ token: otp_code
+ }.to_json
+ )
+ end
+
+ def url(path)
+ BASE_API_URL + path
+ end
+
+ def post(url:, body:, headers: {})
+ Gitlab::HTTP.post(
+ url,
+ headers: {
+ 'Content-Type': 'application/json'
+ }.merge(headers),
+ body: body,
+ verify: false # FTC API Docs specifically mentions to turn off SSL Verification while making requests.
+ )
+ end
+ end
+ end
+ end
+ end
+end