Module: Signet::OAuth2

Defined in:
lib/signet/oauth_2.rb,
lib/signet/oauth_2/client.rb

Overview

An implementation of tools.ietf.org/html/draft-ietf-oauth-v2-10

This module will be updated periodically to support newer drafts of the specification, as they become widely deployed.

Defined Under Namespace

Classes: Client

Class Method Summary collapse

Class Method Details

.generate_authorization_uri(authorization_uri, parameters = {}) ⇒ String

Appends the necessary OAuth parameters to the base authorization endpoint URI.

Parameters:

  • authorization_uri (Addressable::URI, String, #to_str)

    The base authorization endpoint URI.

Returns:

  • (String)

    The authorization URI to redirect the user to.



145
146
147
148
149
150
151
152
153
154
# File 'lib/signet/oauth_2.rb', line 145

def self.generate_authorization_uri(authorization_uri, parameters={})
  for key, value in parameters
    parameters.delete(key) if value == nil
  end
  parsed_uri = Addressable::URI.parse(authorization_uri).dup
  query_values = parsed_uri.query_values || {}
  query_values = query_values.merge(parameters)
  parsed_uri.query_values = query_values
  return parsed_uri.normalize.to_s
end

.generate_basic_authorization_header(client_id, client_password) ⇒ String

Generates a Basic Authorization header from a client identifier and a client password.

Parameters:

  • client_id (String)

    The client identifier.

  • client_password (String)

    The client password.

Returns:

  • (String)

    The value for the HTTP Basic Authorization header.



102
103
104
105
106
107
108
109
110
# File 'lib/signet/oauth_2.rb', line 102

def self.generate_basic_authorization_header(client_id, client_password)
  if client_id =~ /:/
    raise ArgumentError,
      "A client identifier may not contain a ':' character."
  end
  return 'Basic ' + Base64.encode64(
    client_id + ':' + client_password
  ).gsub(/\n/, '')
end

.generate_bearer_authorization_header(access_token, auth_params = nil) ⇒ String

Generates an authorization header for an access token

Parameters:

  • access_token (String)

    The access token.

  • auth_params (Hash) (defaults to: nil)

    Additonal parameters to be encoded in the header

Returns:

  • (String)

    The value for the HTTP Basic Authorization header.



122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/signet/oauth_2.rb', line 122

def self.generate_bearer_authorization_header(
    access_token, auth_params=nil)
  # TODO: escaping?
  header = "Bearer #{access_token}"
  if auth_params && !auth_params.empty?
    header += (", " +
      (auth_params.inject([]) do |accu, (key, value)|
        accu << "#{key}=\"#{value}\""
        accu
      end).join(", ")
    )
  end
  return header
end

.parse_authorization_header(field_value) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/signet/oauth_2.rb', line 28

def self.parse_authorization_header(field_value)
  auth_scheme = field_value[/^([-._0-9a-zA-Z]+)/, 1]
  case auth_scheme
  when /^Basic$/i
    # HTTP Basic is allowed in OAuth 2
    return self.parse_basic_credentials(field_value[/^Basic\s+(.*)$/i, 1])
  when /^OAuth$/i
    # Other token types may be supported eventually
    return self.parse_bearer_credentials(field_value[/^OAuth\s+(.*)$/i, 1])
  else
    raise ParseError,
      'Parsing non-OAuth Authorization headers is out of scope.'
  end
end

.parse_basic_credentials(credential_string) ⇒ Object



55
56
57
58
59
# File 'lib/signet/oauth_2.rb', line 55

def self.parse_basic_credentials(credential_string)
  decoded = Base64.decode64(credential_string)
  client_id, client_secret = decoded.split(':', 2)
  return [['client_id', client_id], ['client_secret', client_secret]]
end

.parse_bearer_credentials(credential_string) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/signet/oauth_2.rb', line 61

def self.parse_bearer_credentials(credential_string)
  access_token = credential_string[/^([^,\s]+)(?:\s|,|$)/i, 1]
  parameters = []
  parameters << ['access_token', access_token]
  auth_param_string = credential_string[/^(?:[^,\s]+)\s*,\s*(.*)$/i, 1]
  if auth_param_string
    # This code will rarely get called, but is included for completeness
    parameters.concat(Signet.parse_auth_param_list(auth_param_string))
  end
  return parameters
end

.parse_credentials(body, content_type) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/signet/oauth_2.rb', line 77

def self.parse_credentials(body, content_type)
  if !body.kind_of?(String)
    raise TypeError, "Expected String, got #{body.class}."
  end
  case content_type
  when /^application\/json.*/
    return MultiJson.load(body)
  when /^application\/x-www-form-urlencoded.*/
    return Hash[Addressable::URI.form_unencode(body)]
  else
    raise ArgumentError, "Invalid content type '#{content_type}'"
  end
end

.parse_oauth_challenge(challenge_string) ⇒ Object



73
74
75
# File 'lib/signet/oauth_2.rb', line 73

def self.parse_oauth_challenge(challenge_string)
  return Signet.parse_auth_param_list(challenge_string)
end

.parse_www_authenticate_header(field_value) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/signet/oauth_2.rb', line 43

def self.parse_www_authenticate_header(field_value)
  auth_scheme = field_value[/^([-._0-9a-zA-Z]+)/, 1]
  case auth_scheme
  when /^OAuth$/i
    # Other token types may be supported eventually
    return self.parse_oauth_challenge(field_value[/^OAuth\s+(.*)$/i, 1])
  else
    raise ParseError,
      'Parsing non-OAuth WWW-Authenticate headers is out of scope.'
  end
end