Class: Rack::Shibboleth

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/shibboleth.rb,
lib/rack/shibboleth/version.rb,
lib/rack/shibboleth/request.rb,
lib/rack/shibboleth/resolver.rb,
lib/rack/shibboleth/response.rb

Defined Under Namespace

Classes: Request, Resolver, Response

Constant Summary

DS =
'ds:http://www.w3.org/2000/09/xmldsig#'
XENC =
'xenc:http://www.w3.org/2001/04/xmlenc#'
VERSION =
'0.0.1'

Instance Method Summary (collapse)

Constructor Details

- (Shibboleth) initialize(app, opts)

Creates a new instance of this middleware to be used. Required options are:

Using this middleware, a client will attempt authentication if the /auth/shibboleth path is visited. Upon successful authentication, the application will be called on the assertion_url path with the Resolver object located in:

env['shibboleth.resolver']

This object can be either nil or a Resolver

Parameters:

  • app

    the application to proxy requests to

  • opts (Hash)

    a hash of options to this shibboleth instance.

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/rack/shibboleth.rb', line 32

def initialize app, opts
  @app = app
  @opts = opts

  if @opts[:private_key].nil? || !::File.exists?(@opts[:private_key])
    raise ArgumentError, 'need valid :private_key option'
  end
  raise ArgumentError, 'need :idp_url option' if @opts[:idp_url].nil?
  raise ArgumentError, 'need :issuer option' if @opts[:issuer].nil?
  raise ArgumentError, 'need :assertion_url option' if @opts[:assertion_url].nil?
  @private_key = OpenSSL::PKey::RSA.new(::File.read(@opts[:private_key]))
end

Instance Method Details

- (Object) call(env)



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/rack/shibboleth.rb', line 45

def call env
  request = Rack::Request.new env
  if request.path_info == '/auth/shibboleth'
    query = {
      :SAMLRequest => Shibboleth::Request.new(@opts).encode,
      :RelayState  => @opts[:issuer]
    }

    arr = query.map{ |k, v| "#{k}=#{Rack::Utils.escape v}" }

    return Rack::Response.new.tap{ |r|
      r.redirect @opts[:idp_url] + '?' + arr.join('&')
    }.finish
  elsif request.path_info == '/Shibboleth.sso/SAML2/POST'
    env['shibboleth.resolver'] = Shibboleth::Resolver.from_response(
      request.params['SAMLResponse'], @private_key, @opts)
  end

  @app.call env
end