Class: Signet::OAuth2::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/signet/oauth_2/client.rb

Constant Summary collapse

OOB_MODES =
["urn:ietf:wg:oauth:2.0:oob:auto", "urn:ietf:wg:oauth:2.0:oob", "oob"].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Client

Creates an OAuth 2.0 client.

Examples:

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'
)

Parameters:

  • options (Hash) (defaults to: {})

    The configuration parameters for the client.

    • :authorization_uri - The authorization server's HTTP endpoint capable of authenticating the end-user and obtaining authorization.

    • :token_credential_uri - The authorization server's HTTP endpoint capable of issuing tokens and refreshing expired tokens.

    • :client_id - A unique identifier issued to the client to identify itself to the authorization server.

    • :client_secret - A shared symmetric secret issued by the authorization server, which is used to authenticate the client.

    • :scope - The scope of the access request, expressed either as an Array or as a space-delimited String.

    • :target_audience - The final target audience for ID tokens fetched by this client, as a String.

    • :state - An arbitrary string designed to allow the client to maintain state.

    • :code - The authorization code received from the authorization server.

    • :redirect_uri - The redirection URI used in the initial request.

    • :username - The resource owner's username.

    • :password - The resource owner's password.

    • :issuer - Issuer ID when using assertion profile

    • :person - Target user for assertions

    • :expiry - Number of seconds assertions are valid for

    • :signing_key - Signing key when using assertion profile

    • :refresh_token - The refresh token associated with the access token to be refreshed.

    • :access_token - The current access token for this client.

    • :id_token - The current ID token for this client.

    • :extension_parameters - When using an extension grant type, this the set of parameters used by that extension.

See Also:


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/signet/oauth_2/client.rb', line 94

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
  @target_audience      = nil
  @state                = nil
  @username             = nil
  @access_type          = nil
  update! options
end

Instance Attribute Details

#subObject

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


611
612
613
# File 'lib/signet/oauth_2/client.rb', line 611

def sub
  @sub
end

Instance Method Details

#access_tokenString

Returns the access token associated with this client.

Returns:

  • (String)

    The access token.


725
726
727
# File 'lib/signet/oauth_2/client.rb', line 725

def access_token
  @access_token ||= nil
end

#access_token=(new_access_token) ⇒ Object

Sets the access token associated with this client.

Parameters:

  • new_access_token (String)

    The access token.


734
735
736
# File 'lib/signet/oauth_2/client.rb', line 734

def access_token= new_access_token
  @access_token = new_access_token
end

#access_typeString, Symbol

Returns the current access type parameter for #authorization_uri.

Returns:

  • (String, Symbol)

    The current access type.


352
353
354
# File 'lib/signet/oauth_2/client.rb', line 352

def access_type
  @access_type
end

#access_type=(new_access_type) ⇒ Object

Sets the current access type parameter for #authorization_uri.

Parameters:

  • new_access_type (String, Symbol)

    The current access type.


361
362
363
# File 'lib/signet/oauth_2/client.rb', line 361

def access_type= new_access_type
  @access_type = new_access_type
end

#additional_parametersHash

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

Returns:

  • (Hash)

    The pass through parameters.


686
687
688
# File 'lib/signet/oauth_2/client.rb', line 686

def additional_parameters
  @additional_parameters ||= {}
end

#additional_parameters=(new_additional_parameters) ⇒ Object

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

Parameters:

  • new_additional_parameters (Hash)

    The parameters.


695
696
697
698
699
700
701
702
# File 'lib/signet/oauth_2/client.rb', line 695

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

#audienceString

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

Returns:

  • (String)

    Target audience ID.


571
572
573
# File 'lib/signet/oauth_2/client.rb', line 571

def audience
  @audience
end

#audience=(new_audience) ⇒ Object

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

Parameters:

  • new_audience (String)

    Target audience ID


581
582
583
# File 'lib/signet/oauth_2/client.rb', line 581

def audience= new_audience
  @audience = new_audience
end

#authorization_uri(options = {}) ⇒ Addressable::URI

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

Returns:

  • (Addressable::URI)

    The authorization URI.

Raises:

  • (ArgumentError)

See Also:


275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/signet/oauth_2/client.rb', line 275

def authorization_uri options = {}
  # Normalize external input
  options = deep_hash_normalize options

  return nil if @authorization_uri.nil?
  options[:response_type] = :code unless options[:response_type]
  options[:access_type] = access_type if !options[:access_type] && access_type
  options[:client_id] ||= client_id
  options[:redirect_uri] ||= redirect_uri
  if options[:prompt] && options[:approval_prompt]
    raise ArgumentError, "prompt and approval_prompt are mutually exclusive parameters"
  end
  raise ArgumentError, "Missing required client identifier." unless options[:client_id]
  raise ArgumentError, "Missing required redirect URI." unless options[:redirect_uri]
  options[:scope] = scope.join " " if !options[:scope] && scope
  options[:state] = state unless options[:state]
  options.merge!(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
  uri
end

#authorization_uri=(new_authorization_uri) ⇒ Object

Sets the authorization URI for this client.

Parameters:

  • new_authorization_uri (Addressable::URI, Hash, String, #to_str)

    The authorization URI.


317
318
319
# File 'lib/signet/oauth_2/client.rb', line 317

def authorization_uri= new_authorization_uri
  @authorization_uri = coerce_uri new_authorization_uri
end

#clear_credentials!Object

Removes all credentials from the client.


866
867
868
869
870
871
872
873
874
875
# File 'lib/signet/oauth_2/client.rb', line 866

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_idString

Returns the client identifier for this client.

Returns:

  • (String)

    The client identifier.


369
370
371
# File 'lib/signet/oauth_2/client.rb', line 369

def client_id
  @client_id
end

#client_id=(new_client_id) ⇒ Object

Sets the client identifier for this client.

Parameters:

  • new_client_id (String)

    The client identifier.


378
379
380
# File 'lib/signet/oauth_2/client.rb', line 378

def client_id= new_client_id
  @client_id = new_client_id
end

#client_secretString

Returns the client secret for this client.

Returns:

  • (String)

    The client secret.


386
387
388
# File 'lib/signet/oauth_2/client.rb', line 386

def client_secret
  @client_secret
end

#client_secret=(new_client_secret) ⇒ Object

Sets the client secret for this client.

Parameters:

  • new_client_secret (String)

    The client secret.


395
396
397
# File 'lib/signet/oauth_2/client.rb', line 395

def client_secret= new_client_secret
  @client_secret = new_client_secret
end

#codeString

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

Returns:

  • (String)

    The authorization code.


472
473
474
# File 'lib/signet/oauth_2/client.rb', line 472

def code
  @code
end

#code=(new_code) ⇒ Object

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

Parameters:

  • new_code (String)

    The authorization code.


482
483
484
# File 'lib/signet/oauth_2/client.rb', line 482

def code= new_code
  @code = new_code
end

#coerce_uri(incoming_uri) ⇒ Object

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


340
341
342
343
344
345
346
# File 'lib/signet/oauth_2/client.rb', line 340

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 = {}, &keyfinder) ⇒ String

Returns the decoded ID token associated with this client.

Parameters:

  • public_key (OpenSSL::PKey::RSA, Object) (defaults to: nil)

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

Returns:

  • (String)

    The decoded ID token.

Raises:


763
764
765
766
767
768
769
770
771
772
773
# File 'lib/signet/oauth_2/client.rb', line 763

def decoded_id_token public_key = nil, options = {}, &keyfinder
  options[:algorithm] ||= signing_algorithm
  verify = !public_key.nil? || block_given?
  payload, _header = JWT.decode(id_token, public_key, verify, options, &keyfinder)
  raise Signet::UnsafeOperationError, "No ID token audience declared." unless payload.key? "aud"
  unless Array(payload["aud"]).include?(client_id)
    raise Signet::UnsafeOperationError,
          "ID token audience did not match Client ID."
  end
  payload
end

#expired?TrueClass, FalseClass

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

Returns:

  • (TrueClass, FalseClass)

    The expiration state of the access token.


847
848
849
# File 'lib/signet/oauth_2/client.rb', line 847

def expired?
  !expires_at.nil? && Time.now >= expires_at
end

#expires_atTime?

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

Returns:

  • (Time, nil)

    The access token lifetime.


827
828
829
# File 'lib/signet/oauth_2/client.rb', line 827

def expires_at
  @expires_at
end

#expires_at=(new_expires_at) ⇒ Object

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.

Parameters:

  • new_expires_at (String, Integer, Time, nil)

    The access token expiration time.


837
838
839
# File 'lib/signet/oauth_2/client.rb', line 837

def expires_at= new_expires_at
  @expires_at = normalize_timestamp new_expires_at
end

#expires_inInteger?

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

Returns:

  • (Integer, nil)

    The access token lifetime.


780
781
782
783
784
785
786
# File 'lib/signet/oauth_2/client.rb', line 780

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) ⇒ Object

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.

Parameters:

  • new_expires_in (String, Integer, nil)

    The access token lifetime.


795
796
797
798
799
800
801
802
803
# File 'lib/signet/oauth_2/client.rb', line 795

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) ⇒ TrueClass, FalseClass

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

Parameters:

  • sec (Integer)

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

Returns:

  • (TrueClass, FalseClass)

    The expiration state of the access token.


860
861
862
# File 'lib/signet/oauth_2/client.rb', line 860

def expires_within? sec
  !expires_at.nil? && Time.now >= (expires_at - sec)
end

#expiryInteger

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

Returns:

  • (Integer)

    Assertion expiry, in seconds


618
619
620
# File 'lib/signet/oauth_2/client.rb', line 618

def expiry
  @expiry
end

#expiry=(new_expiry) ⇒ Object

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

Parameters:

  • new_expiry (Integer, String)

    Assertion expiry, in seconds


628
629
630
# File 'lib/signet/oauth_2/client.rb', line 628

def expiry= new_expiry
  @expiry = new_expiry ? new_expiry.to_i : nil
end

#extension_parametersHash

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

Returns:

  • (Hash)

    The extension parameters.


663
664
665
# File 'lib/signet/oauth_2/client.rb', line 663

def extension_parameters
  @extension_parameters ||= {}
end

#extension_parameters=(new_extension_parameters) ⇒ Object

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

Parameters:

  • new_extension_parameters (Hash)

    The parameters.


673
674
675
676
677
678
679
680
# File 'lib/signet/oauth_2/client.rb', line 673

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 = {}) ⇒ Object

rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/PerceivedComplexity

Raises:

  • (ArgumentError)

1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
# File 'lib/signet/oauth_2/client.rb', line 1011

def fetch_access_token options = {}
  raise ArgumentError, "Missing token endpoint URI." if token_credential_uri.nil?

  options = deep_hash_normalize options

  client = options[:connection] ||= Faraday.default_connection
  url = Addressable::URI.parse(token_credential_uri).normalize.to_s
  parameters = 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

  return ::Signet::OAuth2.parse_credentials body, content_type if status == 200

  message = "  Server message:\n#{response.body.to_s.strip}" unless body.to_s.strip.empty?
  if [400, 401, 403].include? status
    message = "Authorization failed." + message
    raise ::Signet::AuthorizationError.new(
      message, response: response
    )
  elsif status.to_s[0] == "5"
    message = "Remote server error." + message
    raise ::Signet::RemoteServerError, message
  else
    message = "Unexpected status code: #{response.status}." + message
    raise ::Signet::UnexpectedStatusError, message
  end
end

#fetch_access_token!(options = {}) ⇒ Object

rubocop:enable Metrics/AbcSize rubocop:enable Metrics/MethodLength


1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
# File 'lib/signet/oauth_2/client.rb', line 1053

def fetch_access_token! options = {}
  token_hash = 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
    update_token! token_hash
  end
  token_hash
end

#fetch_protected_resource(options = {}) ⇒ Array

Transmits a request for a protected resource.

Examples:

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

Parameters:

  • options (Hash) (defaults to: {})

    The configuration parameters for the request.

    • :request - A pre-constructed request. An OAuth 2 Authorization header will be added to it, as well as an explicit Cache-Control `no-store` directive.

    • :method - The HTTP method for the request. Defaults to 'GET'.

    • :uri - The URI for the request.

    • :headers - The HTTP headers for the request.

    • :body - The HTTP body for the request.

    • :realm - The Authorization realm. See RFC 2617.

    • :connection - The HTTP connection to use. Must be of type Faraday::Connection.

Returns:

  • (Array)

    The response object.

Raises:


1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
# File 'lib/signet/oauth_2/client.rb', line 1174

def fetch_protected_resource options = {}
  options = deep_hash_normalize options

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

#generate_access_token_request(options = {}) ⇒ Array

Generates a request for token credentials.

Parameters:

  • options (Hash) (defaults to: {})

    The configuration parameters for the request.

    • :code - The authorization code.

Returns:

  • (Array)

    The request object.


974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
# File 'lib/signet/oauth_2/client.rb', line 974

def generate_access_token_request options = {}
  options = deep_hash_normalize options

  parameters = { "grant_type" => grant_type }
  case grant_type
  when "authorization_code"
    parameters["code"] = code
    parameters["redirect_uri"] = redirect_uri
  when "password"
    parameters["username"] = username
    parameters["password"] = password
  when "refresh_token"
    parameters["refresh_token"] = refresh_token
  when "urn:ietf:params:oauth:grant-type:jwt-bearer"
    parameters["assertion"] = to_jwt options
  else
    if 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! extension_parameters
  end
  parameters["client_id"] = client_id unless client_id.nil?
  parameters["client_secret"] = client_secret unless client_secret.nil?
  if options[:scope]
    parameters["scope"] = options[:scope]
  elsif options[:use_configured_scope] && !scope.nil?
    parameters["scope"] = scope
  end
  additional = additional_parameters.merge(options[:additional_parameters] || {})
  additional.each { |k, v| parameters[k.to_s] = v }
  parameters
end

#generate_authenticated_request(options = {}) ⇒ Faraday::Request

Generates an authenticated request for protected resources.

Parameters:

  • options (Hash) (defaults to: {})

    The configuration parameters for the request.

    • :request - A pre-constructed request. An OAuth 2 Authorization header will be added to it, as well as an explicit Cache-Control `no-store` directive.

    • :method - The HTTP method for the request. Defaults to 'GET'.

    • :uri - The URI for the request.

    • :headers - The HTTP headers for the request.

    • :body - The HTTP body for the request.

    • :realm - The Authorization realm. See RFC 2617.

Returns:

  • (Faraday::Request)

    The request object.

Raises:

  • (ArgumentError)

1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
# File 'lib/signet/oauth_2/client.rb', line 1095

def generate_authenticated_request options = {}
  options = deep_hash_normalize options

  raise ArgumentError, "Missing access token." if access_token.nil?
  options = {
    realm: nil
  }.merge(options)

  if options[:request].is_a? Faraday::Request
    request = options[:request]
  else
    if options[:request].is_a? 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.is_a? 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)|
      raise ArgumentError, "Missing :#{key} parameter." unless value
    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(
    access_token,
    options[:realm] ? [["realm", options[:realm]]] : nil
  )
  request["Cache-Control"] = "no-store"
  request
end

#grant_typeString

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.

Returns:

  • (String)

    The inferred grant type.


884
885
886
887
888
889
890
891
892
893
894
895
896
# File 'lib/signet/oauth_2/client.rb', line 884

def grant_type
  @grant_type ||= nil
  return @grant_type if @grant_type
  if code && redirect_uri
    "authorization_code"
  elsif refresh_token
    "refresh_token"
  elsif username && password
    "password"
  elsif issuer && signing_key
    "urn:ietf:params:oauth:grant-type:jwt-bearer"
  end
end

#grant_type=(new_grant_type) ⇒ Object


898
899
900
901
902
903
904
905
906
# File 'lib/signet/oauth_2/client.rb', line 898

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_tokenString

Returns the ID token associated with this client.

Returns:

  • (String)

    The ID token.


742
743
744
# File 'lib/signet/oauth_2/client.rb', line 742

def id_token
  @id_token ||= nil
end

#id_token=(new_id_token) ⇒ Object

Sets the ID token associated with this client.

Parameters:

  • new_id_token (String)

    The ID token.


751
752
753
# File 'lib/signet/oauth_2/client.rb', line 751

def id_token= new_id_token
  @id_token = new_id_token
end

#issued_atTime?

Returns the timestamp the access token was issued at.

Returns:

  • (Time, nil)

    The access token issuance time.


809
810
811
# File 'lib/signet/oauth_2/client.rb', line 809

def issued_at
  @issued_at
end

#issued_at=(new_issued_at) ⇒ Object

Sets the timestamp the access token was issued at.

Parameters:

  • new_issued_at (String, Integer, Time)

    The access token issuance time.


818
819
820
# File 'lib/signet/oauth_2/client.rb', line 818

def issued_at= new_issued_at
  @issued_at = normalize_timestamp new_issued_at
end

#issuerString

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

Returns:

  • (String)

    Issuer id.


552
553
554
# File 'lib/signet/oauth_2/client.rb', line 552

def issuer
  @issuer
end

#issuer=(new_issuer) ⇒ Object

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

Parameters:

  • new_issuer (String)

    Issuer ID (typical in email adddress form).


562
563
564
# File 'lib/signet/oauth_2/client.rb', line 562

def issuer= new_issuer
  @issuer = new_issuer
end

#passwordString

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

Returns:

  • (String)

    The password.


533
534
535
# File 'lib/signet/oauth_2/client.rb', line 533

def password
  @password
end

#password=(new_password) ⇒ Object

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

Parameters:

  • new_password (String)

    The password.


543
544
545
# File 'lib/signet/oauth_2/client.rb', line 543

def password= new_password
  @password = new_password
end

#principalString Also known as: person

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

Returns:

  • (String)

    Target user for impersonation.


590
591
592
# File 'lib/signet/oauth_2/client.rb', line 590

def principal
  @principal
end

#principal=(new_person) ⇒ Object Also known as: person=

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

Parameters:

  • new_person (String)

    Target user for impersonation


600
601
602
# File 'lib/signet/oauth_2/client.rb', line 600

def principal= new_person
  @principal = new_person
end

#redirect_uriString

Returns the redirect URI for this client.

Returns:

  • (String)

    The redirect URI.


490
491
492
# File 'lib/signet/oauth_2/client.rb', line 490

def redirect_uri
  @redirect_uri
end

#redirect_uri=(new_redirect_uri) ⇒ Object

Sets the redirect URI for this client.

Parameters:

  • new_redirect_uri (String)

    The redirect URI.


499
500
501
502
503
504
505
506
507
# File 'lib/signet/oauth_2/client.rb', line 499

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.
  unless new_redirect_uri.nil? || new_redirect_uri.absolute? || uri_is_postmessage?(new_redirect_uri) ||
         uri_is_oob?(new_redirect_uri)
    raise ArgumentError, "Redirect URI must be an absolute URI."
  end
  @redirect_uri = new_redirect_uri
end

#refresh!(options = {}) ⇒ Object

Refresh the access token, if possible


1068
1069
1070
# File 'lib/signet/oauth_2/client.rb', line 1068

def refresh! options = {}
  fetch_access_token! options
end

#refresh_tokenString

Returns the refresh token associated with this client.

Returns:

  • (String)

    The refresh token.


708
709
710
# File 'lib/signet/oauth_2/client.rb', line 708

def refresh_token
  @refresh_token ||= nil
end

#refresh_token=(new_refresh_token) ⇒ Object

Sets the refresh token associated with this client.

Parameters:

  • new_refresh_token (String)

    The refresh token.


717
718
719
# File 'lib/signet/oauth_2/client.rb', line 717

def refresh_token= new_refresh_token
  @refresh_token = new_refresh_token
end

#scopeArray

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

Returns:

  • (Array)

    The scope of access the client is requesting.


404
405
406
# File 'lib/signet/oauth_2/client.rb', line 404

def scope
  @scope
end

#scope=(new_scope) ⇒ Object

Sets the scope for this client.

Parameters:

  • new_scope (Array, String)

    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.


415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/signet/oauth_2/client.rb', line 415

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_algorithmString

Algorithm used for signing JWTs

Returns:

  • (String)

    Signing algorithm


654
655
656
# File 'lib/signet/oauth_2/client.rb', line 654

def signing_algorithm
  signing_key.is_a?(String) ? "HS256" : "RS256"
end

#signing_keyString, OpenSSL::PKey

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

Returns:

  • (String, OpenSSL::PKey)

    Signing key


637
638
639
# File 'lib/signet/oauth_2/client.rb', line 637

def signing_key
  @signing_key
end

#signing_key=(new_key) ⇒ Object

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

Parameters:

  • new_key (String, OpenSSL::Pkey)

    Signing key. Either private key for RSA or string for HMAC algorithm


647
648
649
# File 'lib/signet/oauth_2/client.rb', line 647

def signing_key= new_key
  @signing_key = new_key
end

#stateString

Returns the client's current state value.

Returns:

  • (String)

    The state value.


454
455
456
# File 'lib/signet/oauth_2/client.rb', line 454

def state
  @state
end

#state=(new_state) ⇒ Object

Sets the client's current state value.

Parameters:

  • new_state (String)

    The state value.


463
464
465
# File 'lib/signet/oauth_2/client.rb', line 463

def state= new_state
  @state = new_state
end

#target_audienceString

Returns the final target audience for ID tokens fetched by this client.

Returns:

  • (String)

    The target audience.


438
439
440
# File 'lib/signet/oauth_2/client.rb', line 438

def target_audience
  @target_audience
end

#target_audience=(new_target_audience) ⇒ Object

Sets the final target audience for ID tokens fetched by this client.

Parameters:

  • new_target_audience (String)

    The new target audience.


446
447
448
# File 'lib/signet/oauth_2/client.rb', line 446

def target_audience= new_target_audience
  @target_audience = new_target_audience
end

#to_jsonString

Note:

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

Serialize the client object to JSON.

Returns:

  • (String)

    A serialized JSON representation of the client.


934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
# File 'lib/signet/oauth_2/client.rb', line 934

def to_json(*)
  MultiJson.dump(
    "authorization_uri"    => authorization_uri ? authorization_uri.to_s : nil,
    "token_credential_uri" => token_credential_uri ? token_credential_uri.to_s : nil,
    "client_id"            => client_id,
    "client_secret"        => client_secret,
    "scope"                => scope,
    "target_audience"      => target_audience,
    "state"                => state,
    "code"                 => code,
    "redirect_uri"         => redirect_uri ? redirect_uri.to_s : nil,
    "username"             => username,
    "password"             => password,
    "issuer"               => issuer,
    "audience"             => audience,
    "person"               => person,
    "expiry"               => expiry,
    "expires_at"           => expires_at ? expires_at.to_i : nil,
    "signing_key"          => signing_key,
    "refresh_token"        => refresh_token,
    "access_token"         => access_token,
    "id_token"             => id_token,
    "extension_parameters" => extension_parameters
  )
end

#to_jwt(options = {}) ⇒ Object


908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
# File 'lib/signet/oauth_2/client.rb', line 908

def to_jwt options = {}
  options = deep_hash_normalize options

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

#token_credential_uriAddressable::URI

Returns the token credential URI for this client.

Returns:

  • (Addressable::URI)

    The token credential URI.


325
326
327
# File 'lib/signet/oauth_2/client.rb', line 325

def token_credential_uri
  @token_credential_uri
end

#token_credential_uri=(new_token_credential_uri) ⇒ Object

Sets the token credential URI for this client.

Parameters:

  • new_token_credential_uri (Addressable::URI, Hash, String, #to_str)

    The token credential URI.


334
335
336
# File 'lib/signet/oauth_2/client.rb', line 334

def token_credential_uri= new_token_credential_uri
  @token_credential_uri = coerce_uri new_token_credential_uri
end

#update!(options = {}) ⇒ Object

Updates an OAuth 2.0 client.

Examples:

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

Parameters:

  • options (Hash) (defaults to: {})

    The configuration parameters for the client.

    • :authorization_uri - The authorization server's HTTP endpoint capable of authenticating the end-user and obtaining authorization.

    • :token_credential_uri - The authorization server's HTTP endpoint capable of issuing tokens and refreshing expired tokens.

    • :client_id - A unique identifier issued to the client to identify itself to the authorization server.

    • :client_secret - A shared symmetric secret issued by the authorization server, which is used to authenticate the client.

    • :scope - The scope of the access request, expressed either as an Array or as a space-delimited String.

    • :target_audience - The final target audience for ID tokens fetched by this client, as a String.

    • :state - An arbitrary string designed to allow the client to maintain state.

    • :code - The authorization code received from the authorization server.

    • :redirect_uri - The redirection URI used in the initial request.

    • :username - The resource owner's username.

    • :password - The resource owner's password.

    • :issuer - Issuer ID when using assertion profile

    • :audience - Target audience for assertions

    • :person - Target user for assertions

    • :expiry - Number of seconds assertions are valid for

    • :signing_key - Signing key when using assertion profile

    • :refresh_token - The refresh token associated with the access token to be refreshed.

    • :access_token - The current access token for this client.

    • :access_type - The current access type parameter for #authorization_uri.

    • :id_token - The current ID token for this client.

    • :extension_parameters - When using an extension grant type, this is the set of parameters used by that extension.

See Also:


182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/signet/oauth_2/client.rb', line 182

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.key? :authorization_uri
  self.token_credential_uri = options[:token_credential_uri] if options.key? :token_credential_uri
  self.client_id = options[:client_id] if options.key? :client_id
  self.client_secret = options[:client_secret] if options.key? :client_secret
  self.scope = options[:scope] if options.key? :scope
  self.target_audience = options[:target_audience] if options.key? :target_audience
  self.state = options[:state] if options.key? :state
  self.code = options[:code] if options.key? :code
  self.redirect_uri = options[:redirect_uri] if options.key? :redirect_uri
  self.username = options[:username] if options.key? :username
  self.password = options[:password] if options.key? :password
  self.issuer = options[:issuer] if options.key? :issuer
  self.person = options[:person] if options.key? :person
  self.sub = options[:sub] if options.key? :sub
  self.expiry = options[:expiry] || 60
  self.audience = options[:audience] if options.key? :audience
  self.signing_key = options[:signing_key] if options.key? :signing_key
  self.extension_parameters = options[:extension_parameters] || {}
  self.additional_parameters = options[:additional_parameters] || {}
  self.access_type = options.fetch(:access_type) { :offline }
  update_token! options
  self
end

#update_token!(options = {}) ⇒ Object

Updates an OAuth 2.0 client.

Examples:

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

Parameters:

  • options (Hash) (defaults to: {})

    The configuration parameters related to the token.

    • :refresh_token - The refresh token associated with the access token to be refreshed.

    • :access_token - The current access token for this client.

    • :id_token - The current ID token for this client.

    • :expires_in - The time in seconds until access token expiration.

    • :expires_at - The time as an integer number of seconds since the Epoch

    • :issued_at - The timestamp that the token was issued at.

See Also:


241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/signet/oauth_2/client.rb', line 241

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.key? :expires
  self.expires_in = options[:expires_in] if options.key? :expires_in
  self.expires_at = options[:expires_at] if options.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.key? :issued_at

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

  self.access_token = options[:access_token] if options.key? :access_token
  self.refresh_token = options[:refresh_token] if options.key? :refresh_token
  self.id_token = options[:id_token] if options.key? :id_token

  self
end

#usernameString

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

Returns:

  • (String)

    The username.


514
515
516
# File 'lib/signet/oauth_2/client.rb', line 514

def username
  @username
end

#username=(new_username) ⇒ Object

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

Parameters:

  • new_username (String)

    The username.


524
525
526
# File 'lib/signet/oauth_2/client.rb', line 524

def username= new_username
  @username = new_username
end