Class: ApipieBindings::Authenticators::Negotiate

Inherits:
Base
  • Object
show all
Defined in:
lib/apipie_bindings/authenticators/negotiate.rb

Overview

Negotiate authenticator Implements gssapi negotiation with preexisting kerberos ticket Requires a authentication url, the authentication request will be against. This url needs to support auth negotiation and after successful auth it should return ‘set-cookie’ header with session. This session will be initiated in the auth request and the original request will be made with this cookie. Next requests should be already skip the negotiation, please implement Session support in your client, for not using the negotiation on every request.

Instance Attribute Summary

Attributes inherited from Base

#auth_cookie

Instance Method Summary collapse

Methods inherited from Base

#name, #response

Constructor Details

#initialize(authorization_url, auth_request_options = {}) ⇒ Negotiate

Creates new authenticator for Negotiate auth

Parameters:



20
21
22
23
24
25
# File 'lib/apipie_bindings/authenticators/negotiate.rb', line 20

def initialize(authorization_url, auth_request_options = {})
  @authorization_url = authorization_url
  @service = auth_request_options.delete(:service) || 'HTTP'
  auth_request_options[:method] ||= 'get'
  @auth_request_options = auth_request_options
end

Instance Method Details

#authenticate(original_request, args) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/apipie_bindings/authenticators/negotiate.rb', line 37

def authenticate(original_request, args)
  uri = URI.parse(@authorization_url)
  @gsscli = GSSAPI::Simple.new(uri.host, @service)

  token = @gsscli.init_context
  headers = { 'Authorization' => "Negotiate #{Base64.strict_encode64(token)}" }

  RestClient::Request.execute(@auth_request_options.merge(headers: headers, url: @authorization_url)) do |response, request, raw_response|
    if response.code == 401
      raise RestClient::Unauthorized.new(response), 'Negotiation authentication did not pass.'
    end
    if response.code == 302 && response.headers[:location].end_with?('/users/login')
      raise ApipieBindings::ConfigurationError, 'Server misconfiguration detected'
    end

    # This part is only for next calls, that could be simplified if all resources are behind negotiate auth
    itok = Array(raw_response['WWW-Authenticate']).pop.split(/\s+/).last
    @gsscli.init_context(Base64.strict_decode64(itok)) # The context should now return true

    cookie = raw_response['set-cookie'].split('; ')[0]
    @auth_cookie = cookie
    original_request['Cookie'] = cookie
  end

  original_request
end

#error(ex) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/apipie_bindings/authenticators/negotiate.rb', line 27

def error(ex)
  if ex.is_a?(GSSAPI::GssApiError)
    raise ApipieBindings::AuthenticatorError.new(:negotiate, :no_context, ex)
  elsif ex.is_a?(ApipieBindings::ConfigurationError)
    raise ApipieBindings::AuthenticatorError.new(:negotiate, :configuration, ex)
  else
    raise ex
  end
end