Class: HTTPX::Plugins::OAuth::OAuthSession

Inherits:
Object
  • Object
show all
Defined in:
lib/httpx/plugins/oauth.rb

Overview

Implements the bulk of functionality and maintains the state associated with the management of the the lifecycle of an OAuth session.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(issuer:, client_id:, client_secret:, access_token: nil, refresh_token: nil, scope: nil, audience: nil, token_endpoint: nil, grant_type: nil, token_endpoint_auth_method: nil) ⇒ OAuthSession

Returns a new instance of OAuthSession.

Raises:



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
72
73
74
75
# File 'lib/httpx/plugins/oauth.rb', line 38

def initialize(
  issuer:,
  client_id:,
  client_secret:,
  access_token: nil,
  refresh_token: nil,
  scope: nil,
  audience: nil,
  token_endpoint: nil,
  grant_type: nil,
  token_endpoint_auth_method: nil
)
  @issuer = URI(issuer)
  @client_id = client_id
  @client_secret = client_secret
  @token_endpoint = URI(token_endpoint) if token_endpoint
  @scope = case scope
           when String
             scope.split
           when Array
             scope
  end
  @audience = audience
  @access_token = access_token
  @refresh_token = refresh_token
  @token_endpoint_auth_method = String(token_endpoint_auth_method) if token_endpoint_auth_method
  @grant_type = grant_type || (@refresh_token ? "refresh_token" : "client_credentials")
  @access_token = access_token
  @refresh_token = refresh_token

  unless @token_endpoint_auth_method.nil? || SUPPORTED_AUTH_METHODS.include?(@token_endpoint_auth_method)
    raise Error, "#{@token_endpoint_auth_method} is not a supported auth method"
  end

  return if SUPPORTED_GRANT_TYPES.include?(@grant_type)

  raise Error, "#{@grant_type} is not a supported grant type"
end

Instance Attribute Details

#access_tokenObject (readonly)

Returns the value of attribute access_token.



36
37
38
# File 'lib/httpx/plugins/oauth.rb', line 36

def access_token
  @access_token
end

#refresh_tokenObject (readonly)

Returns the value of attribute refresh_token.



36
37
38
# File 'lib/httpx/plugins/oauth.rb', line 36

def refresh_token
  @refresh_token
end

Instance Method Details

#fetch_access_token(http) ⇒ Object

when not available, it uses the http object to request new access and refresh tokens.



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
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/httpx/plugins/oauth.rb', line 92

def fetch_access_token(http)
  return access_token if access_token

  load(http)

  # always prefer refresh token grant if a refresh token is available
  grant_type = @refresh_token ? "refresh_token" : @grant_type

  headers = {} # : Hash[String ,String]
  form_post = {
    "grant_type" => @grant_type,
    "scope" => Array(@scope).join(" "),
    "audience" => @audience,
  }.compact

  # auth
  case token_endpoint_auth_method
  when "client_secret_post"
    form_post["client_id"] = @client_id
    form_post["client_secret"] = @client_secret
  when "client_secret_basic"
    headers["authorization"] = Authentication::Basic.new(@client_id, @client_secret).authenticate
  end

  case grant_type
  when "client_credentials"
    # do nothing
  when "refresh_token"
    raise Error, "cannot use the `\"refresh_token\"` grant type without a refresh token" unless refresh_token

    form_post["refresh_token"] = refresh_token
  end

  # POST /token
  token_request = http.build_request("POST", token_endpoint, headers: headers, form: form_post)

  token_request.headers.delete("authorization") unless token_endpoint_auth_method == "client_secret_basic"

  token_response = http.skip_auth_header { http.request(token_request) }

  begin
    token_response.raise_for_status
  rescue HTTPError => e
    @refresh_token = nil if e.response.status == 401 && (grant_type == "refresh_token")
    raise e
  end

  payload = token_response.json

  @refresh_token = payload["refresh_token"] || @refresh_token
  @access_token = payload["access_token"]
end

#merge(other) ⇒ Object

TODO: remove this after deprecating the ‘:oauth_session` option



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/httpx/plugins/oauth.rb', line 146

def merge(other)
  obj = dup

  case other
  when OAuthSession
    other.instance_variables.each do |ivar|
      val = other.instance_variable_get(ivar)
      next unless val

      obj.instance_variable_set(ivar, val)
    end
  when Hash
    other.each do |k, v|
      obj.instance_variable_set(:"@#{k}", v) if obj.instance_variable_defined?(:"@#{k}")
    end
  end
  obj
end

#reset!Object



87
88
89
# File 'lib/httpx/plugins/oauth.rb', line 87

def reset!
  @access_token = nil
end

#token_endpointObject

returns the URL where to request access and refresh tokens from.



78
79
80
# File 'lib/httpx/plugins/oauth.rb', line 78

def token_endpoint
  @token_endpoint || "#{@issuer}/token"
end

#token_endpoint_auth_methodObject

returns the oauth-documented authorization method to use when requesting a token.



83
84
85
# File 'lib/httpx/plugins/oauth.rb', line 83

def token_endpoint_auth_method
  @token_endpoint_auth_method || "client_secret_basic"
end