summaryrefslogtreecommitdiff
path: root/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb
blob: 079d631e22a39b37c33696819cd6950ab2f10524 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# 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
            )
          end
        end
      end
    end
  end
end