module Cerner::OAuth1a::Protocol

Public: OAuth 1.0a protocol utilities.

Constants

BAD_REQUEST_PROBLEMS

Public: The oauth_problem values that are mapped to HTTP 400 Bad Request. The values come from wiki.oauth.net/w/page/12238543/ProblemReporting and are mapped based on oauth.net/core/1.0/#rfc.section.10.

UNAUTHORIZED_PROBLEMS

Public: The oauth_problem values that are mapped to HTTP 401 Unauthorized. The values come from wiki.oauth.net/w/page/12238543/ProblemReporting and are mapped based on oauth.net/core/1.0/#rfc.section.10.

Public Class Methods

convert_problem_to_http_status(problem, default = :unauthorized) click to toggle source

Public: Converts a oauth_problem value to an HTTP Status using the mappings in ::BAD_REQUEST_PROBLEMS and ::UNAUTHORIZED_PROBLEMS.

problem - A String containing the oauth_problem value. default - An optional Symbol containing the value to return if an

unknown problem value is passed. Defaults to :unauthorized.

Returns :unauthorized, :bad_request or the value passed in the default

parameter.
# File lib/cerner/oauth1a/protocol.rb, line 159
def self.convert_problem_to_http_status(problem, default = :unauthorized)
  return default unless problem

  problem = problem.to_s

  return :unauthorized if UNAUTHORIZED_PROBLEMS.include?(problem)

  return :bad_request if BAD_REQUEST_PROBLEMS.include?(problem)

  default
end
generate_authorization_header(params) click to toggle source

Public: Generates an OAuth HTTP Authorization scheme value, which can be in either an HTTP Authorization or WWW-Authenticate header.

Reference: oauth.net/core/1.0a/#auth_header

params - Hash containing the key-value pairs to build the value with.

Examples

params = { oauth_version: '1.0', oauth_token: 'XYZ' }
Cerner::OAuth1a::Protocol.generate_authorization_header(params)
# => "OAuth oauth_version=\"1.0\",oauth_token=\"XYZ\""

params = { realm: 'https://test.host', oauth_problem: 'token_expired' }
Cerner::OAuth1a::Protocol.generate_www_authenticate_header(params)
# => "OAuth realm=\"https://test.host\",oauth_problem=\"token_expired\""

Returns the String containing the generated value or nil if params is nil or empty.

# File lib/cerner/oauth1a/protocol.rb, line 99
def self.generate_authorization_header(params)
  return unless params && !params.empty?

  realm = "realm=\"#{params.delete(:realm)}\"" if params[:realm]
  realm += ',' if realm && !params.empty?

  encoded_params = params.map { |k, v| "#{percent_encode(k)}=\"#{percent_encode(v)}\"" }

  "OAuth #{realm}#{encoded_params.join(',')}"
end
generate_www_authenticate_header(params)
parse_authorization_header(value) click to toggle source

Public: Parses an OAuth HTTP Authorization scheme value, which can manifest in either an HTTP Authorization or WWW-Authenticate header.

Reference: oauth.net/core/1.0a/#auth_header

value - String containing the value to parse. If nil or doesn't begin with

'OAuth ', then an empty Hash will be returned.

Examples

header = 'OAuth oauth_version="1.0", oauth_token="XYZ"'
Cerner::OAuth1a::Protocol.parse_authorization_header(header)
# => {:oauth_version=>"1.0", :oauth_token=>"XYZ"}

header = 'OAuth realm="https://test.host", oauth_problem="token_expired"'
Cerner::OAuth1a::Protocol.parse_www_authenticate_header(header)
# => {:realm=>"https://test.host", :oauth_problem=>"token_expired"}

header = 'OAuth realm="https://test.host", oauth_problem=token_expired'
Cerner::OAuth1a::Protocol.parse_www_authenticate_header(header)
# => {:realm=>"https://test.host", :oauth_problem=>"token_expired"}

Returns a Hash with symbolized keys of all of the parameters.

# File lib/cerner/oauth1a/protocol.rb, line 57
def self.parse_authorization_header(value)
  params = {}
  return params unless value

  value = value.strip
  return params unless value.size > 6 && value[0..5].casecmp?('OAuth ')

  # trim off 'OAuth ' prefix
  value = value[6..-1]

  # split value on comma separators
  value.split(/,\s*/).each do |kv_part|
    # split each part on '=' separator
    key, value = kv_part.split('=')
    key = URI.decode_www_form_component(key)
    # trim off surrounding double quotes, if they exist
    value = value[1..-2] if value.start_with?('"') && value.end_with?('"')
    value = URI.decode_www_form_component(value)
    params[key.to_sym] = value
  end

  params
end
parse_url_query_string(query) click to toggle source

Public: Parses a URL-encoded query string into a Hash with symbolized keys.

query - String containing a URL-encoded query string to parse.

Returns a Hash with symbolized keys matching the query parameter names.

Raises ArgumentError if query is nil.

# File lib/cerner/oauth1a/protocol.rb, line 28
def self.parse_url_query_string(query)
  raise ArgumentError, 'query is nil' unless query

  Hash[URI.decode_www_form(query).map { |pair| [pair[0].to_sym, pair[1]] }]
end
parse_www_authenticate_header(value)
percent_encode(text) click to toggle source

Public: Encodes the passed text using the percent encoding variant described in the OAuth 1.0a specification.

Reference: tools.ietf.org/html/rfc5849#section-3.6

text - A String containing the text to encode.

Returns a String that has been encoded.

# File lib/cerner/oauth1a/protocol.rb, line 17
def self.percent_encode(text)
  URI.encode_www_form_component(text).gsub('+', '%20')
end
realm_for(uri) click to toggle source

Public: Returns a String containing a realm value from the URI. The String will be a rooted (path removed) and canonicalized URL of the URL passed.

uri - A URI instance containing the URL to construct the realm for.

Returns a String containing the realm value.

Raises ArgumentError if uri is nil.

# File lib/cerner/oauth1a/protocol.rb, line 180
def self.realm_for(uri)
  raise ArgumentError, 'uri is nil' unless uri

  realm = URI("#{uri.scheme}://#{uri.host}:#{uri.port}")
  realm.to_s
end