rack_my_openid 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
 - data/.rvmrc +1 -0
 - data/Gemfile +8 -0
 - data/README.md +68 -0
 - data/Rakefile +1 -0
 - data/lib/rack_my_openid/handler.rb +89 -0
 - data/lib/rack_my_openid/provider.rb +91 -0
 - data/lib/rack_my_openid/version.rb +3 -0
 - data/lib/rack_my_openid/views/decide.erb +7 -0
 - data/lib/rack_my_openid/views/endpoint.erb +3 -0
 - data/lib/rack_my_openid/views/expired.erb +3 -0
 - data/lib/rack_my_openid/views/layout.erb +9 -0
 - data/lib/rack_my_openid.rb +6 -0
 - data/rack_my_openid.gemspec +26 -0
 - data/spec/handler_spec.rb +106 -0
 - data/spec/provider/authentication_spec.rb +28 -0
 - data/spec/provider/decision_spec.rb +38 -0
 - data/spec/provider/endpoint_spec.rb +10 -0
 - data/spec/provider/http_auth_spec.rb +26 -0
 - data/spec/spec_helper.rb +25 -0
 - metadata +116 -0
 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rvmrc
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            rvm use 1.9.3@rails_openid_server
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # rack_my_openid - a one-user OpenID provider solution for rack
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            So you have a Rack/Sinatra/Rails-powered blog and you want to make it an OpenID?
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Now you can do it in under 5 minutes.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ## Operation details
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Rack_my_openid is a simple, single-user OpenID provider inspired by (now deprecated) [phpMyId](http://siege.org/phpmyid.php). It uses 
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            * [ruby-openid](https://github.com/openid/ruby-openid) for the protocol implementation;
         
     | 
| 
      
 12 
     | 
    
         
            +
            * simple Yaml files for storing configuration;
         
     | 
| 
      
 13 
     | 
    
         
            +
            * in-memory storage for authentication data;
         
     | 
| 
      
 14 
     | 
    
         
            +
            * HTTP Digest authentication for security;
         
     | 
| 
      
 15 
     | 
    
         
            +
            * Sinatra and Rack as the server backend.
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            It's designed to be drop-in compatible with any Rails application, since implementing OpenID is a confusing exercise even with ruby-openid. I extracted it from my own site/blog and am continuing to use it there.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            It's fully covered by RSpec tests.
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            See the [OpenID specs](http://openid.net/specs/openid-authentication-2_0.html) if you really want to understand how the whole thing works.
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            ## Installation - Rails 3
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            * Add the `rack_my_openid` gem to your Gemfile
         
     | 
| 
      
 26 
     | 
    
         
            +
            * Add this to your routes:
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    openid_provider = RackMyOpenid::Provider.new(YAML.load_file('config/rack_my_openid.yml'))
         
     | 
| 
      
 29 
     | 
    
         
            +
                    match '/openid' => openid_provider 
         
     | 
| 
      
 30 
     | 
    
         
            +
                    match '/openid/*whatever' => openid_provider 
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                The `/openid` path can't be changed, as of this release.
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            * Create a `config/rack_my_openid.yml` file (see below)
         
     | 
| 
      
 35 
     | 
    
         
            +
            * Restart your Rails app and you're good to go.
         
     | 
| 
      
 36 
     | 
    
         
            +
            * If you make any changes to the config you'll have to restart the app to pick them up.
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            ## Installation - Standalone
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            This assumes that the OpenID is the root path.
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            * Install the `rack_my_openid` gem.
         
     | 
| 
      
 43 
     | 
    
         
            +
            * Create a `config.ru` in your desired path with these contents:
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    require 'rack_my_openid'
         
     | 
| 
      
 46 
     | 
    
         
            +
                    run RackMyOpenid::Provider.new(YAML.load_file('rack_my_openid.yml'))
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            * Create a `rack_my_openid.yml` file (see below) in the same path
         
     | 
| 
      
 49 
     | 
    
         
            +
            * Create empty `/public` and `/tmp` directories in the same path
         
     | 
| 
      
 50 
     | 
    
         
            +
            * Deploy with [Passenger](http://www.modrails.com/documentation/Users%20guide%20Nginx.html#deploying_a_rack_app), [Rackup](https://github.com/rack/rack/wiki/(tutorial)-rackup-howto) or whatever Rack handler you fancy. 
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            ## `rack_my_openid.yml`
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            This is a simple flat Yaml file. The keys are symbols (as of this release).
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            * `:credentials` - run `md5 -s 'yourusername:rack_my_openid:yourpassword'` (or replace rack_my_openid with your realm name if you changed it);
         
     | 
| 
      
 57 
     | 
    
         
            +
            * `:openid` - the actual OpenID identifier that you want to provide;
         
     | 
| 
      
 58 
     | 
    
         
            +
            * `:realm` - the realm for HTTP Digest auth. The default is `"rack_my_openid"`, why would you change it?
         
     | 
| 
      
 59 
     | 
    
         
            +
            * `:endpoint_url` - the URL of the OpenID endpoint (the one that's '/openid'). You shouldn't explicitly declare it
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            ## TODO
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            * Support stores other than memory store
         
     | 
| 
      
 64 
     | 
    
         
            +
            * Support SReg data provision
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            ~ ~ ~
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            (c) Leonid Shevtsov http://leonid.shevtsov.me
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "bundler/gem_tasks"
         
     | 
| 
         @@ -0,0 +1,89 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'openid/server'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'openid/store/memory'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module RackMyOpenid
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Handler
         
     | 
| 
      
 6 
     | 
    
         
            +
                class BadRequest < RuntimeError; end
         
     | 
| 
      
 7 
     | 
    
         
            +
                class UntrustedRealm < RuntimeError
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :realm
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def initialize(realm); @realm = realm; end
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def message; "OpenID realm #{@realm} not trusted by user."; end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def initialize(options)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @options = options
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def handle(params, session)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  if request = openid_server.decode_request(params)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    return openid_server.encode_response handle_openid_request(request, session)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  else
         
     | 
| 
      
 21 
     | 
    
         
            +
                    raise BadRequest
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def cancel(params)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  if request = openid_server.decode_request(params)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    return openid_server.encode_response cancel_check_id_request(request) 
         
     | 
| 
      
 28 
     | 
    
         
            +
                  else
         
     | 
| 
      
 29 
     | 
    
         
            +
                    raise BadRequest
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              private
         
     | 
| 
      
 34 
     | 
    
         
            +
                
         
     | 
| 
      
 35 
     | 
    
         
            +
                def openid_server
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @openid_server ||= OpenID::Server::Server.new(@options[:endpoint_url], openid_store)
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def openid_store
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @openid_store ||= OpenID::Store::Memory 
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
                
         
     | 
| 
      
 43 
     | 
    
         
            +
                # Handle a valid OpenID request
         
     | 
| 
      
 44 
     | 
    
         
            +
                #
         
     | 
| 
      
 45 
     | 
    
         
            +
                # Requests are handled by the standard openid server,
         
     | 
| 
      
 46 
     | 
    
         
            +
                # except the main one - which validates your OpenID.
         
     | 
| 
      
 47 
     | 
    
         
            +
                # So we only have to handle a check_id request
         
     | 
| 
      
 48 
     | 
    
         
            +
                def handle_openid_request(request, session)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  case request
         
     | 
| 
      
 50 
     | 
    
         
            +
                  when OpenID::Server::CheckIDRequest
         
     | 
| 
      
 51 
     | 
    
         
            +
                    return handle_check_id_request(request, session)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  else
         
     | 
| 
      
 53 
     | 
    
         
            +
                    return openid_server.handle_request(request)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def handle_check_id_request(request, session)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  if request_provided_invalid_openid?(request)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    return request.answer(false)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  elsif trusted_realm?(request.realm, session)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    return request.answer(true, nil, @options[:openid])
         
     | 
| 
      
 62 
     | 
    
         
            +
                  else
         
     | 
| 
      
 63 
     | 
    
         
            +
                    raise UntrustedRealm.new(request.realm)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
                
         
     | 
| 
      
 67 
     | 
    
         
            +
                def cancel_check_id_request(request)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  request.answer(false)
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                # Returns true if the request's claimed id is different from ours
         
     | 
| 
      
 72 
     | 
    
         
            +
                # 
         
     | 
| 
      
 73 
     | 
    
         
            +
                # OK, this is an 'inverted truth' method, but it
         
     | 
| 
      
 74 
     | 
    
         
            +
                # seems appropriate since the opposite assertion isn't
         
     | 
| 
      
 75 
     | 
    
         
            +
                # 'inverted' (request can either not pass an id or
         
     | 
| 
      
 76 
     | 
    
         
            +
                # pass a valid id)
         
     | 
| 
      
 77 
     | 
    
         
            +
                def request_provided_invalid_openid?(request)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  !request.id_select && (request.claimed_id != @options[:openid])
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def trusted_realm?(realm, session)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  trusted_realms(session).include? realm
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
                
         
     | 
| 
      
 85 
     | 
    
         
            +
                def trusted_realms(session={})
         
     | 
| 
      
 86 
     | 
    
         
            +
                  @options.fetch(:trusted_realms, []) + session.fetch(:trusted_realms, [])
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
              end
         
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,91 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'cgi'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'sinatra/base'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'rack_my_openid/handler'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module RackMyOpenid
         
     | 
| 
      
 6 
     | 
    
         
            +
              class Provider < Sinatra::Base
         
     | 
| 
      
 7 
     | 
    
         
            +
                set :root, File.dirname(__FILE__)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                use Rack::Session::Pool
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                # authorization
         
     | 
| 
      
 12 
     | 
    
         
            +
                def authorize!
         
     | 
| 
      
 13 
     | 
    
         
            +
                  response = @auth.call(request.env)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  unless response===true
         
     | 
| 
      
 15 
     | 
    
         
            +
                    throw(:halt, response)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Options can contain
         
     | 
| 
      
 20 
     | 
    
         
            +
                #
         
     | 
| 
      
 21 
     | 
    
         
            +
                # * :credentials (required) - `md5 -s 'username:realm:password'`
         
     | 
| 
      
 22 
     | 
    
         
            +
                # * :openid (required) - the OpenID you want to authorize
         
     | 
| 
      
 23 
     | 
    
         
            +
                # * :realm (optional, the default is "rack_my_openid") - an arbitrary resource name for HTTP Authentication
         
     | 
| 
      
 24 
     | 
    
         
            +
                def initialize(options = {})
         
     | 
| 
      
 25 
     | 
    
         
            +
                  super()
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @options = default_options.merge options
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @auth = Rack::Auth::Digest::MD5.new(lambda{|e| true}, @options[:realm]) do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @options[:credentials]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @auth.opaque = $$.to_s
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @auth.passwords_hashed = true
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                get '/openid' do
         
     | 
| 
      
 35 
     | 
    
         
            +
                  if params.empty?
         
     | 
| 
      
 36 
     | 
    
         
            +
                    erb :endpoint
         
     | 
| 
      
 37 
     | 
    
         
            +
                  else
         
     | 
| 
      
 38 
     | 
    
         
            +
                    authorize!
         
     | 
| 
      
 39 
     | 
    
         
            +
                    @options[:endpoint_url] ||= "#{request.scheme}://#{request.host_with_port}#{request.fullpath}"
         
     | 
| 
      
 40 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 41 
     | 
    
         
            +
                      render_openid_response RackMyOpenid::Handler.new(@options).handle(params, session)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    rescue RackMyOpenid::Handler::BadRequest
         
     | 
| 
      
 43 
     | 
    
         
            +
                      status 400
         
     | 
| 
      
 44 
     | 
    
         
            +
                      body 'Bad Request'
         
     | 
| 
      
 45 
     | 
    
         
            +
                    rescue RackMyOpenid::Handler::UntrustedRealm => e
         
     | 
| 
      
 46 
     | 
    
         
            +
                      session[:openid_request_params] = params
         
     | 
| 
      
 47 
     | 
    
         
            +
                      session[:realm] = e.realm
         
     | 
| 
      
 48 
     | 
    
         
            +
                      redirect to('/openid/decide'), 302 
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                get '/openid/decide' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                  authorize!
         
     | 
| 
      
 55 
     | 
    
         
            +
                  if @realm = session[:realm]
         
     | 
| 
      
 56 
     | 
    
         
            +
                    erb :decide
         
     | 
| 
      
 57 
     | 
    
         
            +
                  else
         
     | 
| 
      
 58 
     | 
    
         
            +
                    redirect to('/openid'), 302
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                post '/openid/decide' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  authorize!
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @realm = session.delete(:realm)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 66 
     | 
    
         
            +
                    if params[:yes]
         
     | 
| 
      
 67 
     | 
    
         
            +
                      session[:trusted_realms] ||= []
         
     | 
| 
      
 68 
     | 
    
         
            +
                      session[:trusted_realms] << @realm
         
     | 
| 
      
 69 
     | 
    
         
            +
                      response = RackMyOpenid::Handler.new(@options).handle(session[:openid_request_params], session)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    else
         
     | 
| 
      
 71 
     | 
    
         
            +
                      response RackMyOpenid::Handler.new(@options).cancel(session[:openid_request_params])
         
     | 
| 
      
 72 
     | 
    
         
            +
                    end
         
     | 
| 
      
 73 
     | 
    
         
            +
                    render_openid_response response
         
     | 
| 
      
 74 
     | 
    
         
            +
                  rescue RackMyOpenid::Handler::BadRequest
         
     | 
| 
      
 75 
     | 
    
         
            +
                    erb :expired
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                def render_openid_response(response)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  status response.code
         
     | 
| 
      
 81 
     | 
    
         
            +
                  headers response.headers
         
     | 
| 
      
 82 
     | 
    
         
            +
                  body response.body
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                def default_options
         
     | 
| 
      
 86 
     | 
    
         
            +
                  {
         
     | 
| 
      
 87 
     | 
    
         
            +
                    :realm => 'rack_my_openid'
         
     | 
| 
      
 88 
     | 
    
         
            +
                  }
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.push File.expand_path("../lib", __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "rack_my_openid/version"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.name        = "rack_my_openid"
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.version     = RackMyOpenid::VERSION
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.authors     = ["Leonid Shevtsov"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.email       = ["leonid@shevtsov.me"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.homepage    = "https://github.com/leonid-shevtsov/rack_my_openid"
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.summary     = %q{Single-user OpenID provider implemented as a Rack (Sinatra) application.}
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.description = %q{Would be useful to enable OpenID authorisation with your Ruby/Rails-based blog, personal website or whatever.}
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              s.rubyforge_project = "rack_my_openid"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              s.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 19 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              s.add_runtime_dependency 'sinatra'
         
     | 
| 
      
 22 
     | 
    
         
            +
              s.add_runtime_dependency 'ruby-openid'
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              s.add_development_dependency 'rspec'
         
     | 
| 
      
 25 
     | 
    
         
            +
              s.add_development_dependency 'capybara'
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,106 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            shared_examples_for 'a valid request' do
         
     | 
| 
      
 4 
     | 
    
         
            +
              context 'when realm is trusted via options' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                let(:options_with_realm) { options.merge({:trusted_realms => [request.realm]}) }
         
     | 
| 
      
 6 
     | 
    
         
            +
                it 'should answer true' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                  described_class.new(options_with_realm).handle(params, session).should == 'answered true'
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              context 'when realm is trusted via session' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                let(:session) { {:trusted_realms => [request.realm] } }
         
     | 
| 
      
 13 
     | 
    
         
            +
                it 'should answer true' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                  described_class.new(options).handle(params, session).should == 'answered true'
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
              
         
     | 
| 
      
 18 
     | 
    
         
            +
              context 'when realm is not trusted' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                it 'should raise an error' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 21 
     | 
    
         
            +
                    described_class.new(options).handle(params, session)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  }.to raise_error(RackMyOpenid::Handler::UntrustedRealm)
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            describe RackMyOpenid::Handler do
         
     | 
| 
      
 28 
     | 
    
         
            +
              let(:options) { {:openid => 'http://myopenid.myopenid/' } }
         
     | 
| 
      
 29 
     | 
    
         
            +
              let(:params) { {} }
         
     | 
| 
      
 30 
     | 
    
         
            +
              let(:session) { {} }
         
     | 
| 
      
 31 
     | 
    
         
            +
              let(:server) { 
         
     | 
| 
      
 32 
     | 
    
         
            +
                server = double('OpenID::Server::Server') 
         
     | 
| 
      
 33 
     | 
    
         
            +
                server.should_receive(:decode_request).with(params) { request }
         
     | 
| 
      
 34 
     | 
    
         
            +
                server
         
     | 
| 
      
 35 
     | 
    
         
            +
              }
         
     | 
| 
      
 36 
     | 
    
         
            +
              before(:each) do
         
     | 
| 
      
 37 
     | 
    
         
            +
                OpenID::Server::Server.stub(:new) { server }
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              context 'with bad params' do
         
     | 
| 
      
 41 
     | 
    
         
            +
                let(:params) { {:bad => :params} }
         
     | 
| 
      
 42 
     | 
    
         
            +
                let(:request) { false }
         
     | 
| 
      
 43 
     | 
    
         
            +
              
         
     | 
| 
      
 44 
     | 
    
         
            +
                it 'should raise error' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 46 
     | 
    
         
            +
                    described_class.new(options).handle(params, session)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  }.to raise_error(RackMyOpenid::Handler::BadRequest)
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              context 'with a non-check_id request' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                let(:params) { {:mode => 'some_mode' } }
         
     | 
| 
      
 53 
     | 
    
         
            +
                let(:request) { Object.new } 
         
     | 
| 
      
 54 
     | 
    
         
            +
                let(:response) { double('Response') }
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                it 'should pass the request to the server' do
         
     | 
| 
      
 57 
     | 
    
         
            +
                  server.should_receive(:handle_request).with(request) { response }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  server.should_receive(:encode_response).with(response)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  described_class.new(options).handle(params, session)
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
              context 'with a check_id request' do
         
     | 
| 
      
 64 
     | 
    
         
            +
                let(:params) { {:mode => 'check_id'} }
         
     | 
| 
      
 65 
     | 
    
         
            +
                let(:request) {
         
     | 
| 
      
 66 
     | 
    
         
            +
                  request = OpenID::Server::CheckIDRequest.new(nil, nil, nil)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  request.stub(:realm) { 'http://my.realm' }
         
     | 
| 
      
 68 
     | 
    
         
            +
                  request.stub(:answer).with(true, nil, options[:openid]) { 'answered true' }
         
     | 
| 
      
 69 
     | 
    
         
            +
                  request.stub(:answer).with(false) { 'answered false' }
         
     | 
| 
      
 70 
     | 
    
         
            +
                  request
         
     | 
| 
      
 71 
     | 
    
         
            +
                }
         
     | 
| 
      
 72 
     | 
    
         
            +
                before do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  server.stub(:encode_response) {|params| params }
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                context 'and a valid openid' do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 78 
     | 
    
         
            +
                    request.stub(:id_select) { false }
         
     | 
| 
      
 79 
     | 
    
         
            +
                    request.stub(:claimed_id) { options[:openid] }
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  it_should_behave_like 'a valid request'
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                context 'and an invalid openid' do
         
     | 
| 
      
 86 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 87 
     | 
    
         
            +
                    request.stub(:id_select) { false }
         
     | 
| 
      
 88 
     | 
    
         
            +
                    request.stub(:claimed_id) { 'bad id' }
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  it 'should answer false' do
         
     | 
| 
      
 92 
     | 
    
         
            +
                    described_class.new(options).handle(params, session).should == 'answered false'
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                context 'and no openid' do
         
     | 
| 
      
 97 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 98 
     | 
    
         
            +
                    request.stub(:id_select) { true }
         
     | 
| 
      
 99 
     | 
    
         
            +
                    request.stub(:claimed_id) { nil }
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  it_should_behave_like 'a valid request'
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
              end
         
     | 
| 
      
 105 
     | 
    
         
            +
            end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            feature 'Authentication' do
         
     | 
| 
      
 4 
     | 
    
         
            +
              setup_app
         
     | 
| 
      
 5 
     | 
    
         
            +
              assume_authorization
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              scenario 'Bad request' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                handler.stub(:handle) { raise RackMyOpenid::Handler::BadRequest }
         
     | 
| 
      
 9 
     | 
    
         
            +
                visit '/openid?foo=bar'
         
     | 
| 
      
 10 
     | 
    
         
            +
                page.status_code.should == 400
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              scenario 'Untrusted realm' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                handler.stub(:handle) { raise RackMyOpenid::Handler::UntrustedRealm.new('http://my.realm') }
         
     | 
| 
      
 15 
     | 
    
         
            +
                visit '/openid?foo=bar'
         
     | 
| 
      
 16 
     | 
    
         
            +
                page.current_path.should == '/openid/decide'
         
     | 
| 
      
 17 
     | 
    
         
            +
                page.should have_selector('form')
         
     | 
| 
      
 18 
     | 
    
         
            +
                page.should have_content('http://my.realm')
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              scenario 'Happy case' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                handler.stub(:handle) { OpenID::Server::WebResponse.new(123, {'X-Test' => 'bar'}, 'testbody') } 
         
     | 
| 
      
 23 
     | 
    
         
            +
                visit '/openid?foo=bar'
         
     | 
| 
      
 24 
     | 
    
         
            +
                page.status_code.should == 123
         
     | 
| 
      
 25 
     | 
    
         
            +
                page.response_headers['X-Test'].should == 'bar'
         
     | 
| 
      
 26 
     | 
    
         
            +
                page.source.should == 'testbody'
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            feature 'Decision whether to trust a realm or not' do
         
     | 
| 
      
 2 
     | 
    
         
            +
              setup_app
         
     | 
| 
      
 3 
     | 
    
         
            +
              assume_authorization
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              context 'when accessing decision page directly' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                scenario 'should redirect to the endpoint' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                  visit '/openid/decide'
         
     | 
| 
      
 8 
     | 
    
         
            +
                  page.current_path.should == '/openid'
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              context 'when redirected to the decision page' do
         
     | 
| 
      
 13 
     | 
    
         
            +
                before do
         
     | 
| 
      
 14 
     | 
    
         
            +
                  handler.stub(:handle) { raise RackMyOpenid::Handler::UntrustedRealm.new('http://my.realm') }
         
     | 
| 
      
 15 
     | 
    
         
            +
                  visit '/openid?foo=bar'
         
     | 
| 
      
 16 
     | 
    
         
            +
                  handler.stub(:handle) { OpenID::Server::WebResponse.new(200, {}, 'ok') }
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                scenario 'Trusting the realm - should allow authentication' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                  handler.should_receive(:handle)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  page.click_button('Yes')
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                scenario 'Not trusting the realm - should cancel authentication' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                  handler.should_receive(:cancel)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  page.click_button('No')
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                scenario 'Preserving realm trust' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                  page.click_button('Yes')
         
     | 
| 
      
 31 
     | 
    
         
            +
                  handler.should_receive(:handle) { |params,session|
         
     | 
| 
      
 32 
     | 
    
         
            +
                    session[:trusted_realms].should == ['http://my.realm']
         
     | 
| 
      
 33 
     | 
    
         
            +
                  }
         
     | 
| 
      
 34 
     | 
    
         
            +
                  visit('/openid?foo=bar')
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            feature 'HTTP authorisation' do
         
     | 
| 
      
 4 
     | 
    
         
            +
              setup_app
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              before do
         
     | 
| 
      
 7 
     | 
    
         
            +
                handler.stub(:handle) { OpenID::Server::WebResponse.new(200, {}, 'ok') }
         
     | 
| 
      
 8 
     | 
    
         
            +
                visit '/openid?foo=bar'
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              scenario 'Without authorisation it should propose to authorise' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                page.status_code.should == 401
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              scenario 'With improper authorisation it should reject the request' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                page.driver.browser.digest_authorize('vasya', 'pupkin')
         
     | 
| 
      
 17 
     | 
    
         
            +
                visit '/openid?foo=bar'
         
     | 
| 
      
 18 
     | 
    
         
            +
                page.status_code.should == 401
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              scenario 'With proper authorisation we should handle the request' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                page.driver.browser.digest_authorize('correct_login', 'correct_password')
         
     | 
| 
      
 23 
     | 
    
         
            +
                visit '/openid?foo=bar'
         
     | 
| 
      
 24 
     | 
    
         
            +
                page.status_code.should == 200
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rack_my_openid'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'rspec'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'capybara/rspec'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module AcceptanceHelper
         
     | 
| 
      
 6 
     | 
    
         
            +
              def setup_app
         
     | 
| 
      
 7 
     | 
    
         
            +
                before { Capybara.app = RackMyOpenid::Provider.new({:realm => 'myrealm', :credentials => 'bd1baa373b11c42826d3b15ef77a26d8'}) }
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                let(:handler) { double('RackMyOpenid::Handler') }
         
     | 
| 
      
 10 
     | 
    
         
            +
                before { RackMyOpenid::Handler.stub(:new).and_return(handler) }
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              def assume_authorization
         
     | 
| 
      
 14 
     | 
    
         
            +
                before {
         
     | 
| 
      
 15 
     | 
    
         
            +
                  visit '/openid?foo=bar'
         
     | 
| 
      
 16 
     | 
    
         
            +
                  page.driver.browser.digest_authorize('correct_login', 'correct_password')
         
     | 
| 
      
 17 
     | 
    
         
            +
                  visit '/openid?foo=bar'
         
     | 
| 
      
 18 
     | 
    
         
            +
                }
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            RSpec.configure do |config|
         
     | 
| 
      
 23 
     | 
    
         
            +
              config.extend AcceptanceHelper, :type => :request
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,116 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: rack_my_openid
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.1
         
     | 
| 
      
 5 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 6 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 7 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Leonid Shevtsov
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2012-01-14 00:00:00.000000000 Z
         
     | 
| 
      
 13 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 14 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 15 
     | 
    
         
            +
              name: sinatra
         
     | 
| 
      
 16 
     | 
    
         
            +
              requirement: &70135767507380 !ruby/object:Gem::Requirement
         
     | 
| 
      
 17 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 18 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 19 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 20 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 21 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 22 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 23 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 24 
     | 
    
         
            +
              version_requirements: *70135767507380
         
     | 
| 
      
 25 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 26 
     | 
    
         
            +
              name: ruby-openid
         
     | 
| 
      
 27 
     | 
    
         
            +
              requirement: &70135767506760 !ruby/object:Gem::Requirement
         
     | 
| 
      
 28 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 29 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 30 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 33 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 34 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 35 
     | 
    
         
            +
              version_requirements: *70135767506760
         
     | 
| 
      
 36 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 37 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 38 
     | 
    
         
            +
              requirement: &70135767506180 !ruby/object:Gem::Requirement
         
     | 
| 
      
 39 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 40 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 41 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 42 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 43 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 44 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 45 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 46 
     | 
    
         
            +
              version_requirements: *70135767506180
         
     | 
| 
      
 47 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 48 
     | 
    
         
            +
              name: capybara
         
     | 
| 
      
 49 
     | 
    
         
            +
              requirement: &70135767503520 !ruby/object:Gem::Requirement
         
     | 
| 
      
 50 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 55 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 56 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 57 
     | 
    
         
            +
              version_requirements: *70135767503520
         
     | 
| 
      
 58 
     | 
    
         
            +
            description: Would be useful to enable OpenID authorisation with your Ruby/Rails-based
         
     | 
| 
      
 59 
     | 
    
         
            +
              blog, personal website or whatever.
         
     | 
| 
      
 60 
     | 
    
         
            +
            email:
         
     | 
| 
      
 61 
     | 
    
         
            +
            - leonid@shevtsov.me
         
     | 
| 
      
 62 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 63 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 64 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 65 
     | 
    
         
            +
            files:
         
     | 
| 
      
 66 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 67 
     | 
    
         
            +
            - .rvmrc
         
     | 
| 
      
 68 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 69 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 70 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 71 
     | 
    
         
            +
            - lib/rack_my_openid.rb
         
     | 
| 
      
 72 
     | 
    
         
            +
            - lib/rack_my_openid/handler.rb
         
     | 
| 
      
 73 
     | 
    
         
            +
            - lib/rack_my_openid/provider.rb
         
     | 
| 
      
 74 
     | 
    
         
            +
            - lib/rack_my_openid/version.rb
         
     | 
| 
      
 75 
     | 
    
         
            +
            - lib/rack_my_openid/views/decide.erb
         
     | 
| 
      
 76 
     | 
    
         
            +
            - lib/rack_my_openid/views/endpoint.erb
         
     | 
| 
      
 77 
     | 
    
         
            +
            - lib/rack_my_openid/views/expired.erb
         
     | 
| 
      
 78 
     | 
    
         
            +
            - lib/rack_my_openid/views/layout.erb
         
     | 
| 
      
 79 
     | 
    
         
            +
            - rack_my_openid.gemspec
         
     | 
| 
      
 80 
     | 
    
         
            +
            - spec/handler_spec.rb
         
     | 
| 
      
 81 
     | 
    
         
            +
            - spec/provider/authentication_spec.rb
         
     | 
| 
      
 82 
     | 
    
         
            +
            - spec/provider/decision_spec.rb
         
     | 
| 
      
 83 
     | 
    
         
            +
            - spec/provider/endpoint_spec.rb
         
     | 
| 
      
 84 
     | 
    
         
            +
            - spec/provider/http_auth_spec.rb
         
     | 
| 
      
 85 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 86 
     | 
    
         
            +
            homepage: https://github.com/leonid-shevtsov/rack_my_openid
         
     | 
| 
      
 87 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 88 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 89 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 90 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 91 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 92 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 93 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 94 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 95 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 96 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 97 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 98 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 99 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 100 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 101 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 102 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 103 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 104 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 105 
     | 
    
         
            +
            rubyforge_project: rack_my_openid
         
     | 
| 
      
 106 
     | 
    
         
            +
            rubygems_version: 1.8.11
         
     | 
| 
      
 107 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 108 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 109 
     | 
    
         
            +
            summary: Single-user OpenID provider implemented as a Rack (Sinatra) application.
         
     | 
| 
      
 110 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 111 
     | 
    
         
            +
            - spec/handler_spec.rb
         
     | 
| 
      
 112 
     | 
    
         
            +
            - spec/provider/authentication_spec.rb
         
     | 
| 
      
 113 
     | 
    
         
            +
            - spec/provider/decision_spec.rb
         
     | 
| 
      
 114 
     | 
    
         
            +
            - spec/provider/endpoint_spec.rb
         
     | 
| 
      
 115 
     | 
    
         
            +
            - spec/provider/http_auth_spec.rb
         
     | 
| 
      
 116 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     |