class Signet::OAuth2::Client

Constants

OOB_MODES

Attributes

sub[RW]

The target “sub” when issuing assertions. Used in some Admin SDK APIs.

Public Class Methods

new(options={}) click to toggle source

Creates an OAuth 2.0 client.

@param [Hash] options

The configuration parameters for the client.
- <code>:authorization_uri</code> -
  The authorization server's HTTP endpoint capable of
  authenticating the end-user and obtaining authorization.
- <code>:token_credential_uri</code> -
  The authorization server's HTTP endpoint capable of issuing
  tokens and refreshing expired tokens.
- <code>:client_id</code> -
  A unique identifier issued to the client to identify itself to the
  authorization server.
- <code>:client_secret</code> -
  A shared symmetric secret issued by the authorization server,
  which is used to authenticate the client.
- <code>:scope</code> -
  The scope of the access request, expressed either as an Array
  or as a space-delimited String.
- <code>:state</code> -
  An arbitrary string designed to allow the client to maintain state.
- <code>:code</code> -
  The authorization code received from the authorization server.
- <code>:redirect_uri</code> -
  The redirection URI used in the initial request.
- <code>:username</code> -
  The resource owner's username.
- <code>:password</code> -
  The resource owner's password.
- <code>:issuer</code> -
  Issuer ID when using assertion profile
- <code>:person</code> -
  Target user for assertions
- <code>:expiry</code> -
  Number of seconds assertions are valid for
- <code>:signing_key</code> -
  Signing key when using assertion profile
- <code>:refresh_token</code> -
  The refresh token associated with the access token
  to be refreshed.
- <code>:access_token</code> -
  The current access token for this client.
- <code>:id_token</code> -
  The current ID token for this client.
- <code>:extension_parameters</code> -
  When using an extension grant type, this the set of parameters used
  by that extension.

@example

client = Signet::OAuth2::Client.new(
  :authorization_uri =>
    'https://example.server.com/authorization',
  :token_credential_uri =>
    'https://example.server.com/token',
  :client_id => 'anonymous',
  :client_secret => 'anonymous',
  :scope => 'example',
  :redirect_uri => 'https://example.client.com/oauth'
)

@see #update!

# File lib/signet/oauth_2/client.rb, line 92
def initialize options={}
  @authorization_uri    = nil
  @token_credential_uri = nil
  @client_id            = nil
  @client_secret        = nil
  @code                 = nil
  @expires_at           = nil
  @issued_at            = nil
  @issuer               = nil
  @password             = nil
  @principal            = nil
  @redirect_uri         = nil
  @scope                = nil
  @state                = nil
  @username             = nil
  @access_type          = nil
  self.update!(options)
end

Public Instance Methods

access_token() click to toggle source

Returns the access token associated with this client.

@return [String] The access token.

# File lib/signet/oauth_2/client.rb, line 699
def access_token
  return @access_token ||= nil
end
access_token=(new_access_token) click to toggle source

Sets the access token associated with this client.

@param [String] new_access_token

The access token.
# File lib/signet/oauth_2/client.rb, line 708
def access_token=(new_access_token)
  @access_token = new_access_token
end
access_type() click to toggle source

Returns the current access type parameter for authorization_uri.

@return [String, Symbol] The current access type.

# File lib/signet/oauth_2/client.rb, line 341
def access_type
  return @access_type
end
access_type=(new_access_type) click to toggle source

Sets the current access type parameter for authorization_uri.

@param [String, Symbol] new_access_type

The current access type.
# File lib/signet/oauth_2/client.rb, line 350
def access_type=(new_access_type)
  @access_type = new_access_type
end
additional_parameters() click to toggle source

Returns the set of additional (non standard) parameters to be used by the client.

@return [Hash] The pass through parameters.

# File lib/signet/oauth_2/client.rb, line 660
def additional_parameters
  return @additional_parameters ||= {}
end
additional_parameters=(new_additional_parameters) click to toggle source

Sets additional (non standard) parameters to be used by the client.

@param [Hash] new_additional_parameters

The parameters.
# File lib/signet/oauth_2/client.rb, line 669
def additional_parameters=(new_additional_parameters)
  if new_additional_parameters.respond_to?(:to_hash)
    @additional_parameters = new_additional_parameters.to_hash
  else
    raise TypeError,
          "Expected Hash, got #{new_additional_parameters.class}."
  end
end
audience() click to toggle source

Returns the issuer ID associated with this client. Used only by the assertion grant type.

@return [String] Target audience ID.

# File lib/signet/oauth_2/client.rb, line 544
def audience
  return @audience
end
audience=(new_audience) click to toggle source

Sets the target audience ID when issuing assertions. Used only by the assertion grant type.

@param [String] new_audience

Target audience ID
# File lib/signet/oauth_2/client.rb, line 554
def audience=(new_audience)
  @audience = new_audience
end
authorization_uri(options={}) click to toggle source

Returns the authorization URI that the user should be redirected to.

@return [Addressable::URI] The authorization URI.

@see Signet::OAuth2.generate_authorization_uri

# File lib/signet/oauth_2/client.rb, line 258
def authorization_uri(options={})
  # Normalize external input
  options = deep_hash_normalize(options)

  return nil if @authorization_uri == nil
  unless options[:response_type]
    options[:response_type] = :code
  end
  if !options[:access_type] && access_type
    options[:access_type] = access_type
  end
  options[:client_id] ||= self.client_id
  options[:redirect_uri] ||= self.redirect_uri
  if options[:prompt] && options[:approval_prompt]
    raise ArgumentError, "prompt and approval_prompt are mutually exclusive parameters"
  end
  if !options[:client_id]
    raise ArgumentError, "Missing required client identifier."
  end
  unless options[:redirect_uri]
    raise ArgumentError, "Missing required redirect URI."
  end
  if !options[:scope] && self.scope
    options[:scope] = self.scope.join(' ')
  end
  options[:state] = self.state unless options[:state]
  options.merge!(self.additional_parameters.merge(options[:additional_parameters] || {}))
  options.delete(:additional_parameters)
  options = Hash[options.map do |key, option|
    [key.to_s, option]
  end]
  uri = Addressable::URI.parse(
    ::Signet::OAuth2.generate_authorization_uri(
      @authorization_uri, options
    )
  )
  if uri.normalized_scheme != 'https'
    raise Signet::UnsafeOperationError,
      'Authorization endpoint must be protected by TLS.'
  end
  return uri
end
authorization_uri=(new_authorization_uri) click to toggle source

Sets the authorization URI for this client.

@param [Addressable::URI, Hash, String, to_str] new_authorization_uri

The authorization URI.
# File lib/signet/oauth_2/client.rb, line 306
def authorization_uri=(new_authorization_uri)
  @authorization_uri = coerce_uri(new_authorization_uri)
end
clear_credentials!() click to toggle source

Removes all credentials from the client.

# File lib/signet/oauth_2/client.rb, line 841
def clear_credentials!
  @access_token = nil
  @refresh_token = nil
  @id_token = nil
  @username = nil
  @password = nil
  @code = nil
  @issued_at = nil
  @expires_at = nil
end
client_id() click to toggle source

Returns the client identifier for this client.

@return [String] The client identifier.

# File lib/signet/oauth_2/client.rb, line 358
def client_id
  return @client_id
end
client_id=(new_client_id) click to toggle source

Sets the client identifier for this client.

@param [String] new_client_id

The client identifier.
# File lib/signet/oauth_2/client.rb, line 367
def client_id=(new_client_id)
  @client_id = new_client_id
end
client_secret() click to toggle source

Returns the client secret for this client.

@return [String] The client secret.

# File lib/signet/oauth_2/client.rb, line 375
def client_secret
  return @client_secret
end
client_secret=(new_client_secret) click to toggle source

Sets the client secret for this client.

@param [String] new_client_secret

The client secret.
# File lib/signet/oauth_2/client.rb, line 384
def client_secret=(new_client_secret)
  @client_secret = new_client_secret
end
code() click to toggle source

Returns the authorization code issued to this client. Used only by the authorization code access grant type.

@return [String] The authorization code.

# File lib/signet/oauth_2/client.rb, line 445
def code
  return @code
end
code=(new_code) click to toggle source

Sets the authorization code issued to this client. Used only by the authorization code access grant type.

@param [String] new_code

The authorization code.
# File lib/signet/oauth_2/client.rb, line 455
def code=(new_code)
  @code = new_code
end
coerce_uri(incoming_uri) click to toggle source

Addressable expects URIs formatted as hashes to come in with symbols as keys. Returns nil implicitly for the nil case.

# File lib/signet/oauth_2/client.rb, line 329
def coerce_uri(incoming_uri)
  if incoming_uri.is_a? Hash
    Addressable::URI.new(deep_hash_normalize(incoming_uri))
  elsif incoming_uri
    Addressable::URI.parse(incoming_uri)
  end
end
decoded_id_token(public_key=nil, options = {}) click to toggle source

Returns the decoded ID token associated with this client.

@param [OpenSSL::PKey::RSA, Object] public_key

The public key to use to verify the ID token. Skips verification if
omitted.

@return [String] The decoded ID token.

# File lib/signet/oauth_2/client.rb, line 737
def decoded_id_token public_key=nil, options = {}, &keyfinder
  options[:algorithm] ||= signing_algorithm
  verify = !!(public_key || keyfinder)
  payload, _header = JWT.decode(self.id_token, public_key, verify, options, &keyfinder)
  if !payload.has_key?('aud')
    raise Signet::UnsafeOperationError, 'No ID token audience declared.'
  elsif payload['aud'] != self.client_id
    raise Signet::UnsafeOperationError,
      'ID token audience did not match Client ID.'
  end
  return payload
end
expired?() click to toggle source

Returns true if the access token has expired. Returns false if the token has not expired or has an nil @expires_at.

@return [TrueClass, FalseClass]

The expiration state of the access token.
# File lib/signet/oauth_2/client.rb, line 822
def expired?
  return self.expires_at != nil && Time.now >= self.expires_at
end
expires_at() click to toggle source

Returns the timestamp the access token will expire at. Returns nil if the token does not expire.

@return [Time, nil] The access token lifetime.

# File lib/signet/oauth_2/client.rb, line 802
def expires_at
  @expires_at
end
expires_at=(new_expires_at) click to toggle source

Limits the lifetime of the access token as number of seconds since the Epoch. Nil values will be treated as though the token does not expire. @param [String,Integer,Time, nil] new_expires_at

The access token expiration time.
# File lib/signet/oauth_2/client.rb, line 812
def expires_at=(new_expires_at)
  @expires_at = normalize_timestamp new_expires_at
end
expires_in() click to toggle source

Returns the lifetime of the access token in seconds. Returns nil if the token does not expire.

@return [Integer, nil] The access token lifetime.

# File lib/signet/oauth_2/client.rb, line 755
def expires_in
  if @expires_at.nil? || @issued_at.nil?
    nil
  else
    (@expires_at - @issued_at).to_i
  end
end
expires_in=(new_expires_in) click to toggle source

Sets the lifetime of the access token in seconds. Resets the #issued_at timestamp. Nil values will be treated as though the token does not expire.

@param [String, Integer, nil] new_expires_in

The access token lifetime.
# File lib/signet/oauth_2/client.rb, line 770
def expires_in= new_expires_in
  if !new_expires_in.nil?
    @issued_at = Time.now
    @expires_at = @issued_at + new_expires_in.to_i
  else
    @expires_at = nil
    @issued_at = nil
  end
end
expires_within?(sec) click to toggle source

Returns true if the access token has expired or expires within the next n seconds. Returns false for tokens with a nil @expires_at.

@param [Integer] sec

Max number of seconds from now where a token is still considered
expired.

@return [TrueClass, FalseClass]

The expiration state of the access token.
# File lib/signet/oauth_2/client.rb, line 835
def expires_within?(sec)
  return self.expires_at != nil && Time.now >= (self.expires_at - sec)
end
expiry() click to toggle source

Returns the number of seconds assertions are valid for Used only by the assertion grant type.

@return [Integer] Assertion expiry, in seconds

# File lib/signet/oauth_2/client.rb, line 591
def expiry
  return @expiry
end
expiry=(new_expiry) click to toggle source

Sets the number of seconds assertions are valid for Used only by the assertion grant type.

@param [Integer, String] new_expiry

Assertion expiry, in seconds
# File lib/signet/oauth_2/client.rb, line 601
def expiry=(new_expiry)
  @expiry = new_expiry ? new_expiry.to_i : nil
end
extension_parameters() click to toggle source

Returns the set of extension parameters used by the client. Used only by extension access grant types.

@return [Hash] The extension parameters.

# File lib/signet/oauth_2/client.rb, line 637
def extension_parameters
  return @extension_parameters ||= {}
end
extension_parameters=(new_extension_parameters) click to toggle source

Sets extension parameters used by the client. Used only by extension access grant types.

@param [Hash] new_extension_parameters

The parameters.
# File lib/signet/oauth_2/client.rb, line 647
def extension_parameters=(new_extension_parameters)
  if new_extension_parameters.respond_to?(:to_hash)
    @extension_parameters = new_extension_parameters.to_hash
  else
    raise TypeError,
      "Expected Hash, got #{new_extension_parameters.class}."
  end
end
fetch_access_token(options={}) click to toggle source
# File lib/signet/oauth_2/client.rb, line 985
def fetch_access_token(options={})
  if self.token_credential_uri.nil?
    raise ArgumentError, 'Missing token endpoint URI.'
  end

  options = deep_hash_normalize(options)

  client = options[:connection] ||= Faraday.default_connection
  url = Addressable::URI.parse(self.token_credential_uri).normalize.to_s
  parameters = self.generate_access_token_request(options)
  if client.is_a?(Faraday::Connection)
    response = client.post url,
      Addressable::URI.form_encode(parameters),
      { 'Content-Type' => 'application/x-www-form-urlencoded' }
    status = response.status.to_i
    body = response.body
    content_type = response.headers['Content-type']
  else
    # Hurley
    response = client.post url, parameters
    status = response.status_code.to_i
    body = response.body
    content_type = response.header[:content_type]
  end

  if status == 200
    return ::Signet::OAuth2.parse_credentials(body, content_type)
  elsif [400, 401, 403].include?(status)
    message = 'Authorization failed.'
    if body.to_s.strip.length > 0
      message += "  Server message:\n#{response.body.to_s.strip}"
    end
    raise ::Signet::AuthorizationError.new(
      message, :response => response
    )
  elsif status.to_s[0] == "5"
    message = 'Remote server error.'
    if body.to_s.strip.length > 0
      message += "  Server message:\n#{response.body.to_s.strip}"
    end
    raise ::Signet::RemoteServerError.new(message)
  else
    message = "Unexpected status code: #{response.status}."
    if body.to_s.strip.length > 0
      message += "  Server message:\n#{response.body.to_s.strip}"
    end
    raise ::Signet::UnexpectedStatusError.new(message)
  end
end
fetch_access_token!(options={}) click to toggle source
# File lib/signet/oauth_2/client.rb, line 1035
def fetch_access_token!(options={})
  token_hash = self.fetch_access_token(options)
  if token_hash
    # No-op for grant types other than `authorization_code`.
    # An authorization code is a one-time use token and is immediately
    # revoked after usage.
    self.code = nil
    self.issued_at = Time.now
    self.update_token!(token_hash)
  end
  return token_hash
end
fetch_protected_resource(options={}) click to toggle source

Transmits a request for a protected resource.

@param [Hash] options

The configuration parameters for the request.
- <code>:request</code> -
  A pre-constructed request.  An OAuth 2 Authorization header
  will be added to it, as well as an explicit Cache-Control
  `no-store` directive.
- <code>:method</code> -
  The HTTP method for the request.  Defaults to 'GET'.
- <code>:uri</code> -
  The URI for the request.
- <code>:headers</code> -
  The HTTP headers for the request.
- <code>:body</code> -
  The HTTP body for the request.
- <code>:realm</code> -
  The Authorization realm.  See RFC 2617.
- <code>:connection</code> -
  The HTTP connection to use.
  Must be of type <code>Faraday::Connection</code>.

@example

# Using Net::HTTP
response = client.fetch_protected_resource(
  :uri => 'http://www.example.com/protected/resource'
)

@return [Array] The response object.

# File lib/signet/oauth_2/client.rb, line 1154
def fetch_protected_resource(options={})
  options = deep_hash_normalize(options)

  options[:connection] ||= Faraday.default_connection
  request = self.generate_authenticated_request(options)
  request_env = request.to_env(options[:connection])
  request_env[:request] ||= request
  response = options[:connection].app.call(request_env)
  if response.status.to_i == 401
    # When accessing a protected resource, we only want to raise an
    # error for 401 responses.
    message = 'Authorization failed.'
    if response.body.to_s.strip.length > 0
      message += "  Server message:\n#{response.body.to_s.strip}"
    end
    raise ::Signet::AuthorizationError.new(
      message, :request => request, :response => response
    )
  else
    return response
  end
end
generate_access_token_request(options={}) click to toggle source

Generates a request for token credentials.

@param [Hash] options

The configuration parameters for the request.
- <code>:code</code> -
  The authorization code.

@private @return [Array] The request object.

# File lib/signet/oauth_2/client.rb, line 950
def generate_access_token_request(options={})
  options = deep_hash_normalize(options)

  parameters = {"grant_type" => self.grant_type}
  case self.grant_type
  when 'authorization_code'
    parameters['code'] = self.code
    parameters['redirect_uri'] = self.redirect_uri
  when 'password'
    parameters['username'] = self.username
    parameters['password'] = self.password
  when 'refresh_token'
    parameters['refresh_token'] = self.refresh_token
  when 'urn:ietf:params:oauth:grant-type:jwt-bearer'
    parameters['assertion'] = self.to_jwt(options)
  else
    if self.redirect_uri
      # Grant type was intended to be `authorization_code` because of
      # the presence of the redirect URI.
      raise ArgumentError, 'Missing authorization code.'
    end
    parameters.merge!(self.extension_parameters)
  end
  parameters['client_id'] = self.client_id unless self.client_id.nil?
  parameters['client_secret'] = self.client_secret unless self.client_secret.nil?
  if options[:scope]
    parameters['scope'] = options[:scope]
  elsif options[:use_configured_scope] && !self.scope.nil?
    parameters['scope'] = self.scope
  end
  additional = self.additional_parameters.merge(options[:additional_parameters] || {})
  additional.each { |k, v| parameters[k.to_s] = v }
  parameters
end
generate_authenticated_request(options={}) click to toggle source

Generates an authenticated request for protected resources.

@param [Hash] options

The configuration parameters for the request.
- <code>:request</code> -
  A pre-constructed request.  An OAuth 2 Authorization header
  will be added to it, as well as an explicit Cache-Control
  `no-store` directive.
- <code>:method</code> -
  The HTTP method for the request.  Defaults to 'GET'.
- <code>:uri</code> -
  The URI for the request.
- <code>:headers</code> -
  The HTTP headers for the request.
- <code>:body</code> -
  The HTTP body for the request.
- <code>:realm</code> -
  The Authorization realm.  See RFC 2617.

@return [Faraday::Request] The request object.

# File lib/signet/oauth_2/client.rb, line 1074
def generate_authenticated_request(options={})
  options = deep_hash_normalize(options)

  if self.access_token == nil
    raise ArgumentError, 'Missing access token.'
  end
  options = {
    :realm => nil
  }.merge(options)

  if options[:request].kind_of?(Faraday::Request)
    request = options[:request]
  else
    if options[:request].kind_of?(Array)
      method, uri, headers, body = options[:request]
    else
      method = options[:method] || :get
      uri = options[:uri]
      headers = options[:headers] || []
      body = options[:body] || ''
    end
    headers = headers.to_a if headers.kind_of?(Hash)
    request_components = {
      :method => method,
      :uri => uri,
      :headers => headers,
      :body => body
    }
    # Verify that we have all pieces required to return an HTTP request
    request_components.each do |(key, value)|
      unless value
        raise ArgumentError, "Missing :#{key} parameter."
      end
    end
    method = method.to_s.downcase.to_sym
    request = options[:connection].build_request(method.to_s.downcase.to_sym) do |req|
      req.url(Addressable::URI.parse(uri).normalize.to_s)
      req.headers = Faraday::Utils::Headers.new(headers)
      req.body = body
    end
  end

  request['Authorization'] = ::Signet::OAuth2.generate_bearer_authorization_header(
    self.access_token,
    options[:realm] ? [['realm', options[:realm]]] : nil
  )
  request['Cache-Control'] = 'no-store'
  return request
end
grant_type() click to toggle source

Returns the inferred grant type, based on the current state of the client object. Returns `“none”` if the client has insufficient information to make an in-band authorization request.

@return [String]

The inferred grant type.
# File lib/signet/oauth_2/client.rb, line 860
def grant_type
  @grant_type ||= nil
  if @grant_type
    return @grant_type
  else
    if self.code && self.redirect_uri
      'authorization_code'
    elsif self.refresh_token
      'refresh_token'
    elsif self.username && self.password
      'password'
    elsif self.issuer && self.signing_key
      'urn:ietf:params:oauth:grant-type:jwt-bearer'
    else
      # We don't have sufficient auth information, assume an out-of-band
      # authorization arrangement between the client and server, or an
      # extension grant type.
      nil
    end
  end
end
grant_type=(new_grant_type) click to toggle source
# File lib/signet/oauth_2/client.rb, line 882
def grant_type=(new_grant_type)
  case new_grant_type
  when 'authorization_code', 'refresh_token',
      'password', 'client_credentials'
    @grant_type = new_grant_type
  else
    @grant_type = Addressable::URI.parse(new_grant_type)
  end
end
id_token() click to toggle source

Returns the ID token associated with this client.

@return [String] The ID token.

# File lib/signet/oauth_2/client.rb, line 716
def id_token
  return @id_token ||= nil
end
id_token=(new_id_token) click to toggle source

Sets the ID token associated with this client.

@param [String] new_id_token

The ID token.
# File lib/signet/oauth_2/client.rb, line 725
def id_token=(new_id_token)
  @id_token = new_id_token
end
issued_at() click to toggle source

Returns the timestamp the access token was issued at.

@return [Time, nil] The access token issuance time.

# File lib/signet/oauth_2/client.rb, line 784
def issued_at
  @issued_at
end
issued_at=(new_issued_at) click to toggle source

Sets the timestamp the access token was issued at.

@param [String,Integer,Time] new_issued_at

The access token issuance time.
# File lib/signet/oauth_2/client.rb, line 793
def issued_at=(new_issued_at)
  @issued_at = normalize_timestamp(new_issued_at)
end
issuer() click to toggle source

Returns the issuer ID associated with this client. Used only by the assertion grant type.

@return [String] Issuer id.

# File lib/signet/oauth_2/client.rb, line 525
def issuer
  return @issuer
end
issuer=(new_issuer) click to toggle source

Sets the issuer ID associated with this client. Used only by the assertion grant type.

@param [String] new_issuer

Issuer ID (typical in email adddress form).
# File lib/signet/oauth_2/client.rb, line 535
def issuer=(new_issuer)
  @issuer = new_issuer
end
password() click to toggle source

Returns the password associated with this client. Used only by the resource owner password credential access grant type.

@return [String] The password.

# File lib/signet/oauth_2/client.rb, line 506
def password
  return @password
end
password=(new_password) click to toggle source

Sets the password associated with this client. Used only by the resource owner password credential access grant type.

@param [String] new_password

The password.
# File lib/signet/oauth_2/client.rb, line 516
def password=(new_password)
  @password = new_password
end
person()
Alias for: principal
person=(new_person)
Alias for: principal=
principal() click to toggle source

Returns the target resource owner for impersonation. Used only by the assertion grant type.

@return [String] Target user for impersonation.

# File lib/signet/oauth_2/client.rb, line 563
def principal
  return @principal
end
Also aliased as: person
principal=(new_person) click to toggle source

Sets the target resource owner for impersonation. Used only by the assertion grant type.

@param [String] new_person

Target user for impersonation
# File lib/signet/oauth_2/client.rb, line 573
def principal=(new_person)
  @principal = new_person
end
Also aliased as: person=
redirect_uri() click to toggle source

Returns the redirect URI for this client.

@return [String] The redirect URI.

# File lib/signet/oauth_2/client.rb, line 463
def redirect_uri
  return @redirect_uri
end
redirect_uri=(new_redirect_uri) click to toggle source

Sets the redirect URI for this client.

@param [String] new_redirect_uri

The redirect URI.
# File lib/signet/oauth_2/client.rb, line 472
def redirect_uri=(new_redirect_uri)
  new_redirect_uri = Addressable::URI.parse(new_redirect_uri)
  #TODO - Better solution to allow google postmessage flow. For now, make an exception to the spec.
  if new_redirect_uri == nil|| new_redirect_uri.absolute? || uri_is_postmessage?(new_redirect_uri) || uri_is_oob?(new_redirect_uri)
    @redirect_uri = new_redirect_uri
  else
    raise ArgumentError, "Redirect URI must be an absolute URI."
  end
end
refresh!(options={}) click to toggle source

Refresh the access token, if possible

# File lib/signet/oauth_2/client.rb, line 1050
def refresh!(options={})
  self.fetch_access_token!(options)
end
refresh_token() click to toggle source

Returns the refresh token associated with this client.

@return [String] The refresh token.

# File lib/signet/oauth_2/client.rb, line 682
def refresh_token
  return @refresh_token ||= nil
end
refresh_token=(new_refresh_token) click to toggle source

Sets the refresh token associated with this client.

@param [String] new_refresh_token

The refresh token.
# File lib/signet/oauth_2/client.rb, line 691
def refresh_token=(new_refresh_token)
  @refresh_token = new_refresh_token
end
scope() click to toggle source

Returns the scope for this client. Scope is a list of access ranges defined by the authorization server.

@return [Array] The scope of access the client is requesting.

# File lib/signet/oauth_2/client.rb, line 393
def scope
  return @scope
end
scope=(new_scope) click to toggle source

Sets the scope for this client.

@param [Array, String] new_scope

The scope of access the client is requesting.  This may be
expressed as either an Array of String objects or as a
space-delimited String.
# File lib/signet/oauth_2/client.rb, line 404
def scope=(new_scope)
  case new_scope
  when Array
    new_scope.each do |scope|
      if scope.include?(' ')
        raise ArgumentError,
          "Individual scopes cannot contain the space character."
      end
    end
    @scope = new_scope
  when String
    @scope = new_scope.split(' ')
  when nil
    @scope = nil
  else
    raise TypeError, "Expected Array or String, got #{new_scope.class}"
  end
end
signing_algorithm() click to toggle source

Algorithm used for signing JWTs @return [String] Signing algorithm

# File lib/signet/oauth_2/client.rb, line 628
def signing_algorithm
  self.signing_key.is_a?(String) ? "HS256" : "RS256"
end
signing_key() click to toggle source

Returns the signing key associated with this client. Used only by the assertion grant type.

@return [String,OpenSSL::PKey] Signing key

# File lib/signet/oauth_2/client.rb, line 611
def signing_key
  return @signing_key
end
signing_key=(new_key) click to toggle source

Sets the signing key when issuing assertions. Used only by the assertion grant type.

@param [String, OpenSSL::Pkey] new_key

Signing key. Either private key for RSA or string for HMAC algorithm
# File lib/signet/oauth_2/client.rb, line 621
def signing_key=(new_key)
  @signing_key = new_key
end
state() click to toggle source

Returns the client's current state value.

@return [String] The state value.

# File lib/signet/oauth_2/client.rb, line 427
def state
  return @state
end
state=(new_state) click to toggle source

Sets the client's current state value.

@param [String] new_state

The state value.
# File lib/signet/oauth_2/client.rb, line 436
def state=(new_state)
  @state = new_state
end
to_json(*) click to toggle source

Serialize the client object to JSON.

@note A serialized client contains sensitive information. Persist or transmit with care.

@return [String] A serialized JSON representation of the client.

# File lib/signet/oauth_2/client.rb, line 915
def to_json(*)
  return MultiJson.dump({
    'authorization_uri' => self.authorization_uri ? self.authorization_uri.to_s : nil,
    'token_credential_uri' => self.token_credential_uri ? self.token_credential_uri.to_s : nil,
    'client_id' => self.client_id,
    'client_secret' => self.client_secret,
    'scope' => self.scope,
    'state' => self.state,
    'code' => self.code,
    'redirect_uri' => self.redirect_uri ? self.redirect_uri.to_s : nil,
    'username' => self.username,
    'password' => self.password,
    'issuer' => self.issuer,
    'audience' => self.audience,
    'person' => self.person,
    'expiry' => self.expiry,
    'expires_at' => self.expires_at ? self.expires_at.to_i : nil,
    'signing_key' => self.signing_key,
    'refresh_token' => self.refresh_token,
    'access_token' => self.access_token,
    'id_token' => self.id_token,
    'extension_parameters' => self.extension_parameters
  })
end
to_jwt(options={}) click to toggle source
# File lib/signet/oauth_2/client.rb, line 892
def to_jwt(options={})
  options = deep_hash_normalize(options)

  now = Time.new
  skew = options[:skew] || 60
  assertion = {
    "iss" => self.issuer,
    "aud" => self.audience,
    "exp" => (now + self.expiry).to_i,
    "iat" => (now - skew).to_i
  }
  assertion['scope'] = self.scope.join(' ') unless self.scope.nil?
  assertion['prn'] = self.person unless self.person.nil?
  assertion['sub'] = self.sub unless self.sub.nil?
  JWT.encode(assertion, self.signing_key, self.signing_algorithm)
end
token_credential_uri() click to toggle source

Returns the token credential URI for this client.

@return [Addressable::URI] The token credential URI.

# File lib/signet/oauth_2/client.rb, line 314
def token_credential_uri
  return @token_credential_uri
end
token_credential_uri=(new_token_credential_uri) click to toggle source

Sets the token credential URI for this client.

@param [Addressable::URI, Hash, String, to_str] new_token_credential_uri

The token credential URI.
# File lib/signet/oauth_2/client.rb, line 323
def token_credential_uri=(new_token_credential_uri)
  @token_credential_uri = coerce_uri(new_token_credential_uri)
end
update!(options={}) click to toggle source

Updates an OAuth 2.0 client.

@param [Hash] options

The configuration parameters for the client.
- <code>:authorization_uri</code> -
  The authorization server's HTTP endpoint capable of
  authenticating the end-user and obtaining authorization.
- <code>:token_credential_uri</code> -
  The authorization server's HTTP endpoint capable of issuing
  tokens and refreshing expired tokens.
- <code>:client_id</code> -
  A unique identifier issued to the client to identify itself to the
  authorization server.
- <code>:client_secret</code> -
  A shared symmetric secret issued by the authorization server,
  which is used to authenticate the client.
- <code>:scope</code> -
  The scope of the access request, expressed either as an Array
  or as a space-delimited String.
- <code>:state</code> -
  An arbitrary string designed to allow the client to maintain state.
- <code>:code</code> -
  The authorization code received from the authorization server.
- <code>:redirect_uri</code> -
  The redirection URI used in the initial request.
- <code>:username</code> -
  The resource owner's username.
- <code>:password</code> -
  The resource owner's password.
- <code>:issuer</code> -
  Issuer ID when using assertion profile
- <code>:audience</code> -
  Target audience for assertions
- <code>:person</code> -
  Target user for assertions
- <code>:expiry</code> -
  Number of seconds assertions are valid for
- <code>:signing_key</code> -
  Signing key when using assertion profile
- <code>:refresh_token</code> -
  The refresh token associated with the access token
  to be refreshed.
- <code>:access_token</code> -
  The current access token for this client.
- <code>:access_type</code> -
  The current access type parameter for #authorization_uri.
- <code>:id_token</code> -
  The current ID token for this client.
- <code>:extension_parameters</code> -
  When using an extension grant type, this is the set of parameters used
  by that extension.

@example

client.update!(
  :code => 'i1WsRn1uB1',
  :access_token => 'FJQbwq9',
  :expires_in => 3600
)

@see Signet::OAuth2::Client#initialize @see #update_token!

# File lib/signet/oauth_2/client.rb, line 173
def update!(options={})
  # Normalize all keys to symbols to allow indifferent access.
  options = deep_hash_normalize(options)

  self.authorization_uri = options[:authorization_uri] if options.has_key?(:authorization_uri)
  self.token_credential_uri = options[:token_credential_uri] if options.has_key?(:token_credential_uri)
  self.client_id = options[:client_id] if options.has_key?(:client_id)
  self.client_secret = options[:client_secret] if options.has_key?(:client_secret)
  self.scope = options[:scope] if options.has_key?(:scope)
  self.state = options[:state] if options.has_key?(:state)
  self.code = options[:code] if options.has_key?(:code)
  self.redirect_uri = options[:redirect_uri] if options.has_key?(:redirect_uri)
  self.username = options[:username] if options.has_key?(:username)
  self.password = options[:password] if options.has_key?(:password)
  self.issuer = options[:issuer] if options.has_key?(:issuer)
  self.person = options[:person] if options.has_key?(:person)
  self.sub = options[:sub] if options.has_key?(:sub)
  self.expiry = options[:expiry] || 60
  self.audience = options[:audience] if options.has_key?(:audience)
  self.signing_key = options[:signing_key] if options.has_key?(:signing_key)
  self.extension_parameters = options[:extension_parameters] || {}
  self.additional_parameters = options[:additional_parameters] || {}
  self.access_type = options.fetch(:access_type) { :offline }
  self.update_token!(options)
  return self
end
update_token!(options={}) click to toggle source

Updates an OAuth 2.0 client.

@param [Hash] options

The configuration parameters related to the token.
- <code>:refresh_token</code> -
  The refresh token associated with the access token
  to be refreshed.
- <code>:access_token</code> -
  The current access token for this client.
- <code>:id_token</code> -
  The current ID token for this client.
- <code>:expires_in</code> -
  The time in seconds until access token expiration.
- <code>:expires_at</code> -
  The time as an integer number of seconds since the Epoch
- <code>:issued_at</code> -
  The timestamp that the token was issued at.

@example

client.update!(
  :refresh_token => 'n4E9O119d',
  :access_token => 'FJQbwq9',
  :expires_in => 3600
)

@see Signet::OAuth2::Client#initialize @see #update!

# File lib/signet/oauth_2/client.rb, line 228
def update_token!(options={})
  # Normalize all keys to symbols to allow indifferent access internally
  options = deep_hash_normalize(options)

  self.expires_in = options[:expires] if options.has_key?(:expires)
  self.expires_in = options[:expires_in] if options.has_key?(:expires_in)
  self.expires_at = options[:expires_at] if options.has_key?(:expires_at)

  # By default, the token is issued at `Time.now` when `expires_in` is
  # set, but this can be used to supply a more precise time.
  self.issued_at = options[:issued_at] if options.has_key?(:issued_at)

  # Special case where we want expires_at to be relative to issued_at
  if options.has_key?(:issued_at) && options.has_key?(:expires_in)
    set_relative_expires_at options[:issued_at], options[:expires_in]
  end

  self.access_token = options[:access_token] if options.has_key?(:access_token)
  self.refresh_token = options[:refresh_token] if options.has_key?(:refresh_token)
  self.id_token = options[:id_token] if options.has_key?(:id_token)

  return self
end
username() click to toggle source

Returns the username associated with this client. Used only by the resource owner password credential access grant type.

@return [String] The username.

# File lib/signet/oauth_2/client.rb, line 487
def username
  return @username
end
username=(new_username) click to toggle source

Sets the username associated with this client. Used only by the resource owner password credential access grant type.

@param [String] new_username

The username.
# File lib/signet/oauth_2/client.rb, line 497
def username=(new_username)
  @username = new_username
end

Private Instance Methods

deep_hash_normalize(old_hash) click to toggle source
# File lib/signet/oauth_2/client.rb, line 1202
def deep_hash_normalize(old_hash)
  sym_hash = {}
  old_hash and old_hash.each {|k,v| sym_hash[k.to_sym] = recursive_hash_normalize_keys(v)}
  sym_hash
end
normalize_timestamp(time) click to toggle source
# File lib/signet/oauth_2/client.rb, line 1208
def normalize_timestamp(time)
  case time
  when NilClass
    nil
  when Time
    time
  when DateTime
    time.to_time
  when String
    Time.parse(time)
  when Integer
    Time.at(time)
  else
    fail "Invalid time value #{time}"
  end
end
recursive_hash_normalize_keys(val) click to toggle source

Convert all keys in this hash (nested) to symbols for uniform retrieval

# File lib/signet/oauth_2/client.rb, line 1194
def recursive_hash_normalize_keys(val)
  if val.is_a? Hash
    deep_hash_normalize(val)
  else
    val
  end
end
set_relative_expires_at(issued_at, expires_in) click to toggle source
# File lib/signet/oauth_2/client.rb, line 1225
def set_relative_expires_at(issued_at, expires_in)
  self.issued_at = issued_at
  # Using local expires_in because if self.expires_in is used, it returns
  # the time left before the token expires
  self.expires_at = self.issued_at + expires_in.to_i
end
uri_is_oob?(uri) click to toggle source

Check if the URI is a out-of-band @private

# File lib/signet/oauth_2/client.rb, line 1189
def uri_is_oob?(uri)
  return OOB_MODES.include?(uri.to_s)
end
uri_is_postmessage?(uri) click to toggle source

Check if URI is Google's postmessage flow (not a valid #redirect_uri by spec, but allowed) @private

# File lib/signet/oauth_2/client.rb, line 1182
def uri_is_postmessage?(uri)
  return uri.to_s.casecmp('postmessage') == 0
end