rack-openid-1.4.2/0000755000004100000410000000000012271536570013752 5ustar www-datawww-datarack-openid-1.4.2/data.tar.gz.sig0000444000004100000410000000040012271536570016563 0ustar www-datawww-dataŭ@,5WBI~jG;+|X'ǪS!Y{??-iM?FC8qwhSƐܼ0ڇg͵(0 [ y&-^㺜!~NZ0Ƶ &y>ʸ엠cEuL5bg^goU[ɟ~AsRI,#~ŗs>Xl#z^0g]Z7r3f_2rack-openid-1.4.2/lib/0000755000004100000410000000000012271536570014520 5ustar www-datawww-datarack-openid-1.4.2/lib/rack/0000755000004100000410000000000012271536570015440 5ustar www-datawww-datarack-openid-1.4.2/lib/rack/openid/0000755000004100000410000000000012271536570016716 5ustar www-datawww-datarack-openid-1.4.2/lib/rack/openid/simple_auth.rb0000644000004100000410000000352012271536570021555 0ustar www-datawww-datarequire 'rack/openid' require 'rack/request' module Rack class OpenID # A simple OpenID middleware that restricts access to # a single identifier. # # use Rack::OpenID::SimpleAuth, "http://example.org" # # SimpleAuth will automatically insert the required Rack::OpenID # middleware, so use Rack::OpenID is unnecessary. class SimpleAuth def self.new(*args) Rack::OpenID.new(super) end attr_reader :app, :identifier def initialize(app, identifier) @app = app @identifier = identifier end def call(env) if session_authenticated?(env) app.call(env) elsif successful_response?(env) authenticate_session(env) redirect_to requested_url(env) else authentication_request end end private def session(env) env['rack.session'] || raise_session_error end def raise_session_error raise RuntimeError, 'Rack::OpenID::SimpleAuth requires a session' end def session_authenticated?(env) session(env)['authenticated'] == true end def authenticate_session(env) session(env)['authenticated'] = true end def successful_response?(env) if resp = env[OpenID::RESPONSE] resp.status == :success && resp.display_identifier == identifier end end def requested_url(env) req = Rack::Request.new(env) req.url end def redirect_to(url) [303, {'Content-Type' => 'text/html', 'Location' => url}, []] end def authentication_request [401, { OpenID::AUTHENTICATE_HEADER => www_authenticate_header }, []] end def www_authenticate_header OpenID.build_header(:identifier => identifier) end end end end rack-openid-1.4.2/lib/rack/openid/version.rb0000644000004100000410000000007312271536570020730 0ustar www-datawww-datamodule Rack class OpenID VERSION = "1.4.2" end end rack-openid-1.4.2/lib/rack/openid.rb0000644000004100000410000002140212271536570017242 0ustar www-datawww-datarequire 'rack/request' require 'rack/utils' require 'openid' require 'openid/consumer' require 'openid/extensions/sreg' require 'openid/extensions/ax' require 'openid/extensions/oauth' require 'openid/extensions/pape' module Rack # A Rack middleware that provides a more HTTPish API around the # ruby-openid library. # # You trigger an OpenID request similar to HTTP authentication. # From your app, return a "401 Unauthorized" and a "WWW-Authenticate" # header with the identifier you would like to validate. # # On competition, the OpenID response is automatically verified and # assigned to env["rack.openid.response"]. class OpenID # Helper method for building the "WWW-Authenticate" header value. # # Rack::OpenID.build_header(:identifier => "http://josh.openid.com/") # #=> OpenID identifier="http://josh.openid.com/" def self.build_header(params = {}) 'OpenID ' + params.map { |key, value| if value.is_a?(Array) "#{key}=\"#{value.join(',')}\"" else "#{key}=\"#{value}\"" end }.join(', ') end # Helper method for parsing "WWW-Authenticate" header values into # a hash. # # Rack::OpenID.parse_header("OpenID identifier='http://josh.openid.com/'") # #=> {:identifier => "http://josh.openid.com/"} def self.parse_header(str) params = {} if str =~ AUTHENTICATE_REGEXP str = str.gsub(/#{AUTHENTICATE_REGEXP}\s+/, '') str.split(', ').each { |pair| key, *value = pair.split('=') value = value.join('=') value.gsub!(/^\"/, '').gsub!(/\"$/, "") value = value.split(',') params[key] = value.length > 1 ? value : value.first } end params end class TimeoutResponse include ::OpenID::Consumer::Response STATUS = :failure end class MissingResponse include ::OpenID::Consumer::Response STATUS = :missing end HTTP_METHODS = %w(GET HEAD PUT POST DELETE OPTIONS) RESPONSE = "rack.openid.response" AUTHENTICATE_HEADER = "WWW-Authenticate" AUTHENTICATE_REGEXP = /^OpenID/ URL_FIELD_SELECTOR = lambda { |field| field.to_s =~ %r{^https?://} } # Initialize middleware with application and optional OpenID::Store. # If no store is given, OpenID::Store::Memory is used. # # use Rack::OpenID # # or # # use Rack::OpenID, OpenID::Store::Memcache.new def initialize(app, store = nil) @app = app @store = store || default_store end # Standard Rack +call+ dispatch that accepts an +env+ and # returns a [status, header, body] response. def call(env) req = Rack::Request.new(env) sanitize_params!(req.params) if req.params["openid.mode"] complete_authentication(env) end status, headers, body = @app.call(env) qs = headers[AUTHENTICATE_HEADER] if status.to_i == 401 && qs && qs.match(AUTHENTICATE_REGEXP) begin_authentication(env, qs) else [status, headers, body] end end private def sanitize_params!(params) ['openid.sig', 'openid.response_nonce'].each do |param| (params[param] || '').gsub!(' ', '+') end end def begin_authentication(env, qs) req = Rack::Request.new(env) params = self.class.parse_header(qs) session = env["rack.session"] unless session raise RuntimeError, "Rack::OpenID requires a session" end consumer = ::OpenID::Consumer.new(session, @store) identifier = params['identifier'] || params['identity'] begin oidreq = consumer.begin(identifier) add_simple_registration_fields(oidreq, params) add_attribute_exchange_fields(oidreq, params) add_oauth_fields(oidreq, params) add_pape_fields(oidreq, params) url = open_id_redirect_url(req, oidreq, params) return redirect_to(url) rescue ::OpenID::OpenIDError, Timeout::Error => e env[RESPONSE] = MissingResponse.new return @app.call(env) end end def complete_authentication(env) req = Rack::Request.new(env) session = env["rack.session"] unless session raise RuntimeError, "Rack::OpenID requires a session" end oidresp = timeout_protection_from_identity_server { consumer = ::OpenID::Consumer.new(session, @store) consumer.complete(flatten_params(req.params), req.url) } env[RESPONSE] = oidresp method = req.GET["_method"] override_request_method(env, method) sanitize_query_string(env) end def flatten_params(params) Rack::Utils.parse_query(Rack::Utils.build_nested_query(params)) end def override_request_method(env, method) return unless method method = method.upcase if HTTP_METHODS.include?(method) env["REQUEST_METHOD"] = method end end def sanitize_query_string(env) query_hash = env["rack.request.query_hash"] query_hash.delete("_method") query_hash.delete_if do |key, value| key =~ /^openid\./ end env["QUERY_STRING"] = env["rack.request.query_string"] = Rack::Utils.build_query(env["rack.request.query_hash"]) qs = env["QUERY_STRING"] request_uri = (env["PATH_INFO"] || "").dup request_uri << "?" + qs unless qs == "" env["REQUEST_URI"] = request_uri end def scheme_with_host_and_port(req, host = nil) url = req.scheme + "://" url << (host || req.host) scheme, port = req.scheme, req.port if scheme == "https" && port != 443 || scheme == "http" && port != 80 url << ":#{port}" end url end def realm(req, domain = nil) if domain scheme_with_host_and_port(req, domain) else scheme_with_host_and_port(req) end end def request_url(req) url = scheme_with_host_and_port(req) url << req.script_name url << req.path_info url << "?#{req.query_string}" if req.query_string.to_s.length > 0 url end def redirect_to(url) [303, {"Content-Type" => "text/html", "Location" => url}, []] end def open_id_redirect_url(req, oidreq, options) trust_root = options["trust_root"] return_to = options["return_to"] method = options["method"] immediate = options["immediate"] == "true" realm = realm(req, options["realm_domain"]) request_url = request_url(req) if return_to method ||= "get" else return_to = request_url method ||= req.request_method end method = method.to_s.downcase oidreq.return_to_args['_method'] = method unless method == "get" oidreq.redirect_url(trust_root || realm, return_to || request_url, immediate) end def add_simple_registration_fields(oidreq, fields) sregreq = ::OpenID::SReg::Request.new required = Array(fields['required']).reject(&URL_FIELD_SELECTOR) sregreq.request_fields(required, true) if required.any? optional = Array(fields['optional']).reject(&URL_FIELD_SELECTOR) sregreq.request_fields(optional, false) if optional.any? policy_url = fields['policy_url'] sregreq.policy_url = policy_url if policy_url oidreq.add_extension(sregreq) end def add_attribute_exchange_fields(oidreq, fields) axreq = ::OpenID::AX::FetchRequest.new required = Array(fields['required']).select(&URL_FIELD_SELECTOR) optional = Array(fields['optional']).select(&URL_FIELD_SELECTOR) if required.any? || optional.any? required.each do |field| axreq.add(::OpenID::AX::AttrInfo.new(field, nil, true)) end optional.each do |field| axreq.add(::OpenID::AX::AttrInfo.new(field, nil, false)) end oidreq.add_extension(axreq) end end def add_oauth_fields(oidreq, fields) if (consumer = fields['oauth[consumer]']) && (scope = fields['oauth[scope]']) oauthreq = ::OpenID::OAuth::Request.new(consumer, Array(scope).join(' ')) oidreq.add_extension(oauthreq) end end def add_pape_fields(oidreq, fields) preferred_auth_policies = fields['pape[preferred_auth_policies]'] max_auth_age = fields['pape[max_auth_age]'] if preferred_auth_policies || max_auth_age preferred_auth_policies = preferred_auth_policies.split if preferred_auth_policies.is_a?(String) pape_request = ::OpenID::PAPE::Request.new(preferred_auth_policies || [], max_auth_age) oidreq.add_extension(pape_request) end end def default_store require 'openid/store/memory' ::OpenID::Store::Memory.new end def timeout_protection_from_identity_server yield rescue Timeout::Error TimeoutResponse.new end end end rack-openid-1.4.2/metadata.yml0000644000004100000410000000561212271536570016261 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: rack-openid version: !ruby/object:Gem::Version version: 1.4.2 platform: ruby authors: - Michael Grosser - Joshua Peek autorequire: bindir: bin cert_chain: - | -----BEGIN CERTIFICATE----- MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0 MB4XDTEzMDIwMzE4MTMxMVoXDTE0MDIwMzE4MTMxMVowPzEQMA4GA1UEAwwHbWlj aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO 6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R /88CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUsiNnXHtKeMYYcr4yJVmQ WONL+IwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAlyN7kKo/NQCQ0 AOzZLZ3WAePvStkCFIJ53tsv5Kyo4pMAllv+BgPzzBt7qi605mFSL6zBd9uLou+W Co3s48p1dy7CjjAfVQdmVNHF3MwXtfC2OEyvSQPi4xKR8iba8wa3xp9LVo1PuLpw /6DsrChWw74HfsJN6qJOK684hJeT8lBYAUfiC3wD0owoPSg+XtyAAddisR+KV5Y1 NmVHuLtQcNTZy+gRht3ahJRMuC6QyLmkTsf+6MaenwAMkAgHdswGsJztOnNnBa3F y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU ycwMXfl0 -----END CERTIFICATE----- date: 2014-01-20 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rack requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.1.0 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 1.1.0 - !ruby/object:Gem::Dependency name: ruby-openid requirement: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 2.1.8 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: 2.1.8 description: email: michael@grosser.it executables: [] extensions: [] extra_rdoc_files: [] files: - lib/rack/openid.rb - lib/rack/openid/simple_auth.rb - lib/rack/openid/version.rb homepage: https://github.com/grosser/rack-openid licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.0.14 signing_key: specification_version: 4 summary: Provides a more HTTPish API around the ruby-openid library test_files: [] rack-openid-1.4.2/checksums.yaml.gz.sig0000444000004100000410000000040012271536570020013 0ustar www-datawww-dataZJ/S2+$I])k= …}Uiꅥ ~tG_Bb_W%!q̗N)_;iJ# 2YYd w$67>a;?~543~G вjra?lergJME~{[ol딕Rn 'L7"l;Ŋ ]ۃwl: 7Ě2Dž~-`":