Class: HTTPX::Plugins::OAuth::OAuthSession
- Inherits:
-
Object
- Object
- HTTPX::Plugins::OAuth::OAuthSession
- Defined in:
- lib/httpx/plugins/oauth.rb,
sig/plugins/oauth.rbs
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
-
#access_token ⇒ String?
readonly
Returns the value of attribute access_token.
-
#refresh_token ⇒ String?
readonly
Returns the value of attribute refresh_token.
Instance Method Summary collapse
- #expires_at ⇒ Object
-
#fetch_access_token(http) ⇒ String
when not available, it uses the
httpobject to request new access and refresh tokens. -
#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
constructor
A new instance of OAuthSession.
-
#load(http) ⇒ void
uses
httpto fetch for the oauth server metadata. -
#merge(other) ⇒ instance
TODO: remove this after deprecating the
:oauth_sessionoption. - #reset! ⇒ void
-
#token_endpoint ⇒ uri
returns the URL where to request access and refresh tokens from.
-
#token_endpoint_auth_method ⇒ String
returns the oauth-documented authorization method to use when requesting a token.
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.
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 72 73 74 |
# File 'lib/httpx/plugins/oauth.rb', line 37 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") @expires_at = nil @token_mon = Monitor.new 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_token ⇒ String? (readonly)
Returns the value of attribute access_token.
90 91 92 93 94 95 96 97 98 |
# File 'lib/httpx/plugins/oauth.rb', line 90 def access_token @token_mon.synchronize do if (expires_at = @expires_at) && expires_at < Time.now.to_i reset! end @access_token end end |
#refresh_token ⇒ String? (readonly)
Returns the value of attribute refresh_token.
189 190 191 |
# File 'lib/httpx/plugins/oauth.rb', line 189 def refresh_token @token_mon.synchronize { @refresh_token } end |
Instance Method Details
#expires_at ⇒ Object
86 87 88 |
# File 'lib/httpx/plugins/oauth.rb', line 86 def expires_at @token_mon.synchronize { @expires_at } end |
#fetch_access_token(http) ⇒ String
when not available, it uses the http object to request new access and refresh tokens.
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 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/httpx/plugins/oauth.rb', line 107 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" ref_token = refresh_token raise Error, "cannot use the `\"refresh_token\"` grant type without a refresh token" unless ref_token form_post["refresh_token"] = ref_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 @token_mon.synchronize do @refresh_token = payload.fetch("refresh_token", @refresh_token) if (expires_in = payload["expires_in"]) @expires_at = Time.now.to_i + Integer(expires_in) end @access_token = payload["access_token"] end end |
#load(http) ⇒ void
This method returns an undefined value.
uses http to fetch for the oauth server metadata.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/httpx/plugins/oauth.rb', line 194 def load(http) return if @grant_type && @scope = http.skip_auth_header { http.get("#{@issuer}/.well-known/oauth-authorization-server").raise_for_status.json } @token_mon.synchronize do @token_endpoint = ["token_endpoint"] @scope = ["scopes_supported"] @grant_type = Array(["grant_types_supported"]).find { |gr| SUPPORTED_GRANT_TYPES.include?(gr) } @token_endpoint_auth_method = Array(["token_endpoint_auth_methods_supported"]).find do |am| SUPPORTED_AUTH_METHODS.include?(am) end end nil end |
#merge(other) ⇒ instance
TODO: remove this after deprecating the :oauth_session option
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/httpx/plugins/oauth.rb', line 168 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! ⇒ void
This method returns an undefined value.
100 101 102 103 104 |
# File 'lib/httpx/plugins/oauth.rb', line 100 def reset! @token_mon.synchronize do @access_token = @expires_at = nil end end |
#token_endpoint ⇒ uri
returns the URL where to request access and refresh tokens from.
77 78 79 |
# File 'lib/httpx/plugins/oauth.rb', line 77 def token_endpoint @token_endpoint || "#{@issuer}/token" end |
#token_endpoint_auth_method ⇒ String
returns the oauth-documented authorization method to use when requesting a token.
82 83 84 |
# File 'lib/httpx/plugins/oauth.rb', line 82 def token_endpoint_auth_method @token_endpoint_auth_method || "client_secret_basic" end |