Class: Rack::OpenID::Proxy

Inherits:
Object show all
Defined in:
lib/rack-openid-proxy.rb

Overview

A simple OpenID Proxy Rack application / middleware

Notes

  • This requires that a Rack::Session middleware be enabled

  • This requires that the Rack::OpenID middleware be enabled (for now)

Constant Summary collapse

OPENID_RESPONSE =

this is stored in the Rack env (it gets set by Rack::OpenID)

'rack.openid.response'
RETURN_PATH =

this is stored in the session

'rack-openid-proxy.return_path'
DEFAULT_OPTIONS =
{
  :path                    => '/openid',
  :token_store             => {},
  :force_ssl               => false,
  :delete_token_on_request => true
}

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Proxy



62
63
64
65
66
67
68
69
70
# File 'lib/rack-openid-proxy.rb', line 62

def initialize *args
  @app    = args.shift if args.first.respond_to? :call
  options = args.first || {}

  DEFAULT_OPTIONS.each {|name, value| send "#{name}=", value }
  options.each         {|name, value| send "#{name}=", value } if options

  raise_validation_exception unless valid?
end

Class Attribute Details

.formattersObject

Returns the value of attribute formatters.



29
30
31
# File 'lib/rack-openid-proxy.rb', line 29

def formatters
  @formatters
end

Instance Attribute Details

#delete_token_on_requestObject

If set to true, tokens and their responses will be deleted after the first time they are requested



58
59
60
# File 'lib/rack-openid-proxy.rb', line 58

def delete_token_on_request
  @delete_token_on_request
end

#force_sslObject

If set to true, any OpenID-related requests that come in to this app as http:// will be redirected to https://



54
55
56
# File 'lib/rack-openid-proxy.rb', line 54

def force_ssl
  @force_ssl
end

#pathObject

The path that, when requested, does OpenID authentication

  • When used as a middleware, any other paths will call the inner Rack app

  • When used as a standalone all, any other paths will return a 404



50
51
52
# File 'lib/rack-openid-proxy.rb', line 50

def path
  @path
end

#token_storeObject

Returns the value of attribute token_store.



60
61
62
# File 'lib/rack-openid-proxy.rb', line 60

def token_store
  @token_store
end

Instance Method Details

#call(env) ⇒ Object



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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/rack-openid-proxy.rb', line 72

def call env
  request = Rack::Request.new env

  if request.path_info =~ /^#{ path }\.?(.*)/
    format = $1

    if response = env[OPENID_RESPONSE]
      token = "#{ Time.now.to_i }-#{ Digest::SHA2.hexdigest(response.to_yaml) }"
      set token, response
      uri = URI.parse env['rack.session'][RETURN_PATH]
      uri.query = (uri.query.nil?) ? "token=#{token}" : "#{uri.query}&token=#{URI.escape(token)}"
      [ 302, {'Location' => uri.to_s }, [] ]

    elsif token = request.params['token']
      return [ 302, {'Location' => request.url.to_s.sub('http','https')}, [] 
             ] if force_ssl && request.scheme != 'https' && env['HTTP_X_FORWARDED_PROTO'] != 'https'
      response = get token
      if response
        render response, format
      else
        [ 200, {'Content-Type' => 'text/html'}, ["Token not found"] ]
      end

    elsif request.params['url']
      env['rack.session'][RETURN_PATH] = request.referer
      return [ 302, {'Location' => request.url.to_s.sub('http','https')}, [] 
             ] if force_ssl && request.scheme != 'https' && env['HTTP_X_FORWARDED_PROTO'] != 'https'
      [ 401, {'WWW-Authenticate' => "OpenID identifier=\"#{ request.params['url'] }\""}, ["Redirecting to OpenID login ..."] ]

    else
      return [ 302, {'Location' => request.url.to_s.sub('http','https')}, [] 
             ] if force_ssl && request.scheme != 'https' && env['HTTP_X_FORWARDED_PROTO'] != 'https'
      [ 200, {'Content-Type' => 'text/html'}, ["Unknown action.  Did you forget to set ?url= or ?token= ?"] ]
    end

  elsif @app
    @app.call env

  else
    [ 404, {'Content-Type' => 'text/html'}, ["Page not found"] ]
  end
end

#get(token) ⇒ Object



115
116
117
118
119
# File 'lib/rack-openid-proxy.rb', line 115

def get token
  response = token_store[token]
  token_store.delete token if delete_token_on_request
  response
end

#set(token, response) ⇒ Object



121
122
123
# File 'lib/rack-openid-proxy.rb', line 121

def set token, response
  token_store[token] = response
end