Class: OpenAI::Auth::WorkloadIdentityAuth

Inherits:
Object
  • Object
show all
Defined in:
lib/openai/auth/workload_identity_auth.rb,
sig/openai/auth.rbs

Constant Summary collapse

SUBJECT_TOKEN_TYPES =
{
  TokenType::JWT => "urn:ietf:params:oauth:token-type:jwt",
  TokenType::ID => "urn:ietf:params:oauth:token-type:id_token"
}.freeze
TOKEN_EXCHANGE_GRANT_TYPE =
"urn:ietf:params:oauth:grant-type:token-exchange"
DEFAULT_TOKEN_EXCHANGE_URL =
"https://auth.openai.com/oauth/token"
DEFAULT_REFRESH_BUFFER_SECONDS =
1200

Instance Method Summary collapse

Constructor Details

#initialize(config, organization_id, token_exchange_url: DEFAULT_TOKEN_EXCHANGE_URL, token_exchange: nil) ⇒ WorkloadIdentityAuth

Returns a new instance of WorkloadIdentityAuth.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/openai/auth/workload_identity_auth.rb', line 25

def initialize(
  config,
  organization_id,
  token_exchange_url: DEFAULT_TOKEN_EXCHANGE_URL,
  token_exchange: nil
)
  @config = config
  @organization_id = organization_id
  @token_exchange_url = URI(token_exchange_url)
  @token_exchange = token_exchange

  @cached_token = nil
  @cached_token_expires_at_monotonic = nil
  @cached_token_refresh_at_monotonic = nil
  @issued_token_expirations = {}
  @rejected_tokens = {}
  @refreshing = false
  @refresh_generation = nil
  @refresh_error = nil
  @mutex = Mutex.new
  @cond_var = ConditionVariable.new
end

Instance Method Details

#bound_to?(identity, transport:) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:



150
151
152
153
154
# File 'lib/openai/auth/workload_identity_auth.rb', line 150

def bound_to?(identity, transport:)
  @config.equal?(identity) &&
    X509Transport.exact_instance?(@token_exchange, X509TokenExchange) &&
    @token_exchange.bound_to?(identity, transport: transport)
end

#get_token(deadline: nil) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • deadline (Float, nil) (defaults to: nil) —

    absolute monotonic deadline for this request

  • deadline: (Float, nil) (defaults to: nil)

Returns:

  • (String)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/openai/auth/workload_identity_auth.rb', line 52

def get_token(deadline: nil)
  loop do
    check_deadline!(deadline)
    action = nil
    token = nil
    generation = nil
    previous_token = nil

    # Installing refresh cleanup is part of the state transition. No async
    # exception may observe @refreshing after it changes but before the ensure.
    Thread.handle_interrupt(Exception => :never) do
      @mutex.synchronize do
        if @refreshing
          if token_unusable?
            action = :wait
            generation = @refresh_generation
          else
            token = @cached_token
            action = :return
          end
        elsif token_unusable? || needs_refresh?
          previous_token = @cached_token
          @refreshing = true
          generation = {complete: false, error: nil, token: nil, expires_at: nil}
          @refresh_generation = generation
          action = :refresh
        else
          token = @cached_token
          action = :return
        end
      end

      if action == :refresh
        begin
          Thread.handle_interrupt(Exception => :immediate) do
            perform_refresh(deadline: deadline)
          end

        rescue StandardError => error
          fallback = false
          @mutex.synchronize do
            now = OpenAI::Internal::Util.monotonic_secs unless @token_exchange.nil?
            if now && proactive_refresh_fallback?(error, previous_token, deadline, now)
              remaining = @cached_token_expires_at_monotonic - now
              @cached_token_refresh_at_monotonic = now + [5.0, remaining / 2].min
              @refresh_error = error
              fallback = true
            else
              @refresh_error = error unless @token_exchange.nil?
              generation[:error] = error
            end
          end

          raise unless fallback
        ensure
          @mutex.synchronize do
            if generation[:error].nil?
              generation[:token] = @cached_token
              generation[:expires_at] = @cached_token_expires_at_monotonic
            end

            generation[:complete] = true
            @refreshing = false
            @cond_var.broadcast
          end
        end
      end
    end

    return token if action == :return
    if action == :wait
      token = wait_for_refresh(deadline, generation)
      return token unless token.nil?

      next
    end

    return current_token(deadline)
  end
end

#inspect ⇒ String

Avoid exposing cached access tokens or identity configuration in diagnostics.

Returns:

  • (String)


159
160
161
# File 'lib/openai/auth/workload_identity_auth.rb', line 159

def inspect
  "#<#{self.class.name}:0x#{object_id.to_s(16)}>"
end

#invalidate_token(rejected_token = nil) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Parameters:

  • rejected_token (String, nil) (defaults to: nil)


134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/openai/auth/workload_identity_auth.rb', line 134

def invalidate_token(rejected_token = nil)
  @mutex.synchronize do
    if @token_exchange && rejected_token
      expires_at = @issued_token_expirations[rejected_token]
      @rejected_tokens[rejected_token] = expires_at unless expires_at.nil?
    end

    return nil unless rejected_token.nil? || rejected_token == @cached_token

    @cached_token = nil
    @cached_token_expires_at_monotonic = nil
    @cached_token_refresh_at_monotonic = nil
  end
end