Class: OmniAuth::Strategies::UcamRaven

Inherits:
Object
  • Object
show all
Includes:
OmniAuth::Strategy
Defined in:
lib/omniauth/strategies/ucam-raven.rb

Constant Summary collapse

RAVEN_URL =
'https://raven.cam.ac.uk/auth/authenticate.html'
GOOSE_URL =
'https://auth.srcf.net/wls/authenticate'

Instance Method Summary collapse

Constructor Details

#initialize(*args, &block) ⇒ UcamRaven

This method is called when the strategy is instantiated.



37
38
39
40
41
42
43
44
# File 'lib/omniauth/strategies/ucam-raven.rb', line 37

def initialize(*args, &block)
  super(*args, &block)
  raise 'Raven public key data not given' if options.key_data.nil?
  raise 'Raven public key data not correctly formatted' unless options.key_data.is_a?(Array)
  options.key_data.each do |e|
    raise 'Raven public key data not correctly formatted' unless e.is_a?(Array) && e.length == 2
  end
end

Instance Method Details

#callback_phaseObject

This method is called after the user authenticates to Raven and is redirected back to the application.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/omniauth/strategies/ucam-raven.rb', line 63

def callback_phase
  # Check the response is in the format we're expecting.
  return fail!(:wls_response_not_present) if wls_response.nil? || wls_response == ""
  return fail!(:authentication_cancelled_by_user) if wls_response[1].to_i == 410
  return fail!(:no_mutually_acceptable_authentication_types_available) if wls_response[1].to_i == 510
  return fail!(:unsupported_protocol_version) if wls_response[1].to_i == 520
  return fail!(:general_request_parameter_error) if wls_response[1].to_i == 530
  return fail!(:interaction_would_be_required) if wls_response[1].to_i == 540
  return fail!(:waa_not_authorised) if wls_response[1].to_i == 560
  return fail!(:authentication_declined) if wls_response[1].to_i == 570
  return fail!(:invalid_response_status) unless wls_response[1].to_i == 200
  return fail!(:raven_version_mismatch) unless wls_response[0].to_i == 3
  return fail!(:invalid_response_url) unless wls_response[5] == callback_url.split('?').first
  return fail!(:too_few_wls_response_parameters) if wls_response.length < 14
  return fail!(:too_many_wls_response_parameters) if wls_response.length > 14

  # Check the time skew in seconds.
  return fail!(:invalid_issue) unless wls_response[3].length == 16
  skew = ((DateTime.now.new_offset(0) - date_from_rfc3339(wls_response[3])) * 24 * 60 * 60).to_i
  return fail!(:skew_too_large) unless skew.abs < options.skew

  # Check that the RSA key ID and signature are correct.
  options.key_data.each do |kid, kpath|
    if wls_response[12].to_i == kid.to_i
      signed_part = wls_response.first(12).join('!')
      base64_part = wls_response[13].tr('-._','+/=')
      signature = Base64.decode64(base64_part)
      file_contents = File.read(kpath)
      key = OpenSSL::PKey::RSA.new(file_contents)
      digest  = OpenSSL::Digest::SHA1.new
      return fail!(:rsa_signature_check_failed) unless key.verify(digest, signature, signed_part)
      return super
    end
  end
  return fail!(:unknown_rsa_key_id)
end

#request_phaseObject

This method is called when the user initiates a login. It redirects them to the Raven service for authentication.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/omniauth/strategies/ucam-raven.rb', line 47

def request_phase
  url = (options.url || options.honk ? GOOSE_URL : RAVEN_URL).dup
  url << "?ver=3"
  url << "&url=#{callback_url}"
  url << "&desc=#{URI::encode options.desc}" if options.desc
  url << "&aauth=#{URI::encode options.aauth}" if options.aauth
  url << "&iact=#{URI::encode options.iact}" if options.iact
  url << "&msg=#{URI::encode options.msg}" if options.msg
  url << "&params=#{URI::encode options.params}" if options.params
  url << "&date=#{date_to_rfc3339}" if options.date
  # The skew parameter is DEPRECATED and SHOULD NOT be included in requests to the WLS.
  url << "&fail=#{URI::encode options.fail}" if options.fail
  redirect url
end