Class: Aker::Cas::RackProxyCallback

Inherits:
Object
  • Object
show all
Defined in:
lib/aker/cas/rack_proxy_callback.rb

Overview

Rack code for handling the PGT callback part of the CAS proxy authentication protocol. The class itself is middleware; it can also generate an endpoint.

## Behavior

As middleware, this class intercepts and handles two paths and passes all other requests down the chain. The paths are:

  • ‘/receive_pgt`: implements the PGT callback process per section 2.5.4 of the CAS protocol.

  • ‘/retrieve_pgt`: allows an application to retrieve the PGT for a PGTIOU. The PGTIOU is returned to the application as part of the CAS ticket validation process. It should be passed to `/receive_pgt` as the `pgtIou` query parameter. Note that a given PGT may only be retrieved once.

As a full rack app, it handles the same two paths and returns ‘404 Not Found` for all other requests.

## Middleware vs. Application

It is only appropriate to use the class as middleware in a **multithreaded or multiprocessing deployment**. If your application only has one executor at a time, using this class as middleware **will cause a deadlock** during CAS authentication.

## Based on

This class was heavily influenced by ‘CasProxyCallbackController` in rubycas-client. That class has approximately the same behavior, but is Rails-specific.

Constant Summary collapse

RETRIEVE_PATH =
"/retrieve_pgt"
RECEIVE_PATH =
"/receive_pgt"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ RackProxyCallback

Create a new instance of the middleware.

Parameters:

  • app (#call)

    the next rack application in the chain.

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :store (String)

    the file where the middleware will store the received PGTs until they are retrieved.



53
54
55
56
57
# File 'lib/aker/cas/rack_proxy_callback.rb', line 53

def initialize(app, options={})
  @app = app
  @store_filename = options.delete(:store) or
    raise "Please specify a filename for the PGT store"
end

Class Method Details

.application(options = {}) ⇒ #call

Creates a rack application which responds as described in the class overview.

Parameters:

  • options (Hash) (defaults to: {})

    the same options that you can pass to #initialize.

Returns:

  • (#call)

    a full rack application



80
81
82
83
84
85
# File 'lib/aker/cas/rack_proxy_callback.rb', line 80

def self.application(options={})
  app = lambda { |env|
    [404, { "Content-Type" => "text/plain" }, ["Unknown resource #{env['PATH_INFO']}"]]
  }
  RackProxyCallback.new(app, options)
end

Instance Method Details

#call(env) ⇒ Array

Handles a single request in the manner specified in the class overview.

Parameters:

  • env (Hash)

    the rack environment for the request.

Returns:

  • (Array)

    an appropriate rack response.



66
67
68
69
70
# File 'lib/aker/cas/rack_proxy_callback.rb', line 66

def call(env)
  return receive(env) if env["PATH_INFO"] == RECEIVE_PATH
  return retrieve(env) if env["PATH_INFO"] == RETRIEVE_PATH
  @app.call(env)
end