Rework OpenID tests for new flows using OmniAuth mocking

This commit is contained in:
Tom Hughes 2015-02-21 16:41:52 +00:00
parent b0150caee6
commit eaf4b32a7f
17 changed files with 101 additions and 897 deletions

View file

@ -14,3 +14,16 @@ end
Rails.application.config.middleware.use OmniAuth::Builder do
provider :openid, :name => "openid", :store => openid_store
end
# Pending fix for: https://github.com/intridea/omniauth/pull/795
module OmniAuth
module Strategy
def mock_callback_call_with_origin
@env["omniauth.origin"] = session["omniauth.origin"]
mock_callback_call_without_origin
end
alias_method_chain :mock_callback_call, :origin
end
end

View file

@ -107,7 +107,7 @@ openid_user:
creation_time: "2008-05-01 01:23:45"
display_name: openIDuser
data_public: true
openid_url: http://localhost:1123/john.doe?openid.success=true
openid_url: http://localhost:1123/john.doe
terms_agreed: "2010-01-01 11:22:33"
terms_seen: true
languages: en

View file

@ -4,7 +4,12 @@ class UserCreationTest < ActionDispatch::IntegrationTest
fixtures :users
def setup
openid_setup
OmniAuth.config.test_mode = true
end
def teardown
OmniAuth.config.mock_auth[:openid] = nil
OmniAuth.config.test_mode = false
end
def test_create_user_form
@ -143,19 +148,25 @@ class UserCreationTest < ActionDispatch::IntegrationTest
end
def test_user_create_openid_success
OmniAuth.config.add_mock(:openid, :uid => "http://localhost:1123/new.tester")
new_email = "newtester-openid@osm.org"
display_name = "new_tester-openid"
password = "testtest"
assert_difference("User.count") do
assert_difference("ActionMailer::Base.deliveries.size", 1) do
post "/user/new",
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/john.doe?openid.success=newuser", :pass_crypt => "", :pass_crypt_confirmation => "" }
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" }
assert_response :redirect
assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
follow_redirect!
assert_response :redirect
res = openid_request(@response.redirect_url)
get "/user/new", res
assert_redirected_to "/user/terms"
post "/user/save",
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/john.doe?openid.success=newuser", :pass_crypt => password, :pass_crypt_confirmation => password }
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/new.tester", :pass_crypt => password, :pass_crypt_confirmation => password }
assert_response :redirect
follow_redirect!
end
@ -169,15 +180,25 @@ class UserCreationTest < ActionDispatch::IntegrationTest
end
def test_user_create_openid_failure
OmniAuth.config.mock_auth[:openid] = :connection_failed
new_email = "newtester-openid2@osm.org"
display_name = "new_tester-openid2"
assert_difference("User.count", 0) do
assert_difference("ActionMailer::Base.deliveries.size", 0) do
post "/user/new",
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/john.doe?openid.failure=newuser", :pass_crypt => "", :pass_crypt_confirmation => "" }
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" }
assert_response :redirect
res = openid_request(@response.redirect_url)
get "/user/new", res
assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_failure_path(:strategy => "openid", :message => "connection_failed", :origin => "/user/new")
follow_redirect!
assert_response :redirect
follow_redirect!
assert_response :success
assert_template "user/new"
end
@ -187,6 +208,8 @@ class UserCreationTest < ActionDispatch::IntegrationTest
end
def test_user_create_openid_redirect
OmniAuth.config.add_mock(:openid, :uid => "http://localhost:1123/new.tester")
new_email = "redirect_tester_openid@osm.org"
display_name = "redirect_tester_openid"
# nothing special about this page, just need a protected page to redirect back to.
@ -194,13 +217,17 @@ class UserCreationTest < ActionDispatch::IntegrationTest
assert_difference("User.count") do
assert_difference("ActionMailer::Base.deliveries.size", 1) do
post "/user/new",
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/john.doe?openid.success=newuser", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/new.tester", :pass_crypt => "", :pass_crypt_confirmation => "" }, :referer => referer
assert_response :redirect
assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/new.tester", :origin => "/user/new")
follow_redirect!
assert_response :redirect
res = openid_request(@response.location)
get "/user/new", res
assert_redirected_to "/user/terms"
post_via_redirect "/user/save",
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/john.doe?openid.success=newuser", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" }
:user => { :email => new_email, :email_confirmation => new_email, :display_name => display_name, :openid_url => "http://localhost:1123/new.tester", :pass_crypt => "testtest", :pass_crypt_confirmation => "testtest" }
end
end

View file

@ -4,7 +4,12 @@ class UserLoginTest < ActionDispatch::IntegrationTest
fixtures :users
def setup
openid_setup
OmniAuth.config.test_mode = true
end
def teardown
OmniAuth.config.mock_auth[:openid] = nil
OmniAuth.config.test_mode = false
end
def test_login_email_password_normal
@ -284,16 +289,20 @@ class UserLoginTest < ActionDispatch::IntegrationTest
end
def test_login_openid_success
OmniAuth.config.add_mock(:openid, :uid => "http://localhost:1123/john.doe")
get "/login"
assert_response :redirect
assert_redirected_to "controller" => "user", "action" => "login", "cookie_test" => "true"
follow_redirect!
assert_response :success
post "/login", "openid_url" => "http://localhost:1123/john.doe?openid.success=true", :referer => "/history"
post "/login", "openid_url" => "http://localhost:1123/john.doe", :referer => "/history"
assert_response :redirect
post "/login", openid_request(@response.redirect_url)
assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/john.doe", :origin => "/login")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/john.doe", :origin => "/login")
follow_redirect!
assert_response :redirect
follow_redirect!
assert_response :success
@ -301,66 +310,73 @@ class UserLoginTest < ActionDispatch::IntegrationTest
assert_select "span.username", "openIDuser"
end
def test_login_openid_cancel
def test_login_openid_connection_failed
OmniAuth.config.mock_auth[:openid] = :connection_failed
get "/login"
assert_response :redirect
assert_redirected_to "controller" => "user", "action" => "login", "cookie_test" => "true"
follow_redirect!
assert_response :success
post "/login", "openid_url" => "http://localhost:1123/john.doe", :referer => "/diary"
post "/login", "openid_url" => "http://localhost:1123/john.doe", :referer => "/history"
assert_response :redirect
post "/login", openid_request(@response.redirect_url)
assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/john.doe", :origin => "/login")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/john.doe", :origin => "/login")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_failure_path(:strategy => "openid", :message => "connection_failed", :origin => "/login")
follow_redirect!
assert_response :redirect
follow_redirect!
assert_response :success
assert_template "login"
assert_select "div.flash.error", "Connection to authentication provider failed"
assert_select "span.username", false
end
def test_login_openid_invalid_provider
get "/login"
assert_response :redirect
assert_redirected_to "controller" => "user", "action" => "login", "cookie_test" => "true"
follow_redirect!
assert_response :success
# Use a different port that doesn't have the OpenID provider running on to test an invalid openID
post "/login", "openid_url" => "http://localhost:1124/john.doe", :referer => "/diary"
assert_response :redirect
follow_redirect!
assert_response :success
assert_template "login"
assert_select "span.username", false
end
def test_login_openid_invalid_credentials
OmniAuth.config.mock_auth[:openid] = :invalid_credentials
def test_login_openid_invalid_url
get "/login"
assert_response :redirect
assert_redirected_to "controller" => "user", "action" => "login", "cookie_test" => "true"
follow_redirect!
assert_response :success
# Use a url with an invalid protocol to make sure it handles that correctly too
post "/login", "openid_url" => "htt://localhost:1123/john.doe", :referer => "/diary"
post "/login", "openid_url" => "http://localhost:1123/john.doe", :referer => "/history"
assert_response :redirect
assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/john.doe", :origin => "/login")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/john.doe", :origin => "/login")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_failure_path(:strategy => "openid", :message => "invalid_credentials", :origin => "/login")
follow_redirect!
assert_response :redirect
follow_redirect!
assert_response :success
assert_template "login"
assert_select "div.flash.error", "Invalid authentication credentials"
assert_select "span.username", false
end
def test_login_openid_unknown
OmniAuth.config.add_mock(:openid, :uid => "http://localhost:1123/fred.bloggs")
get "/login"
assert_response :redirect
assert_redirected_to "controller" => "user", "action" => "login", "cookie_test" => "true"
follow_redirect!
assert_response :success
post "/login", "openid_url" => "http://localhost:1123/john.doe?openid.success=true_somethingelse", :referer => "/diary"
post "/login", "openid_url" => "http://localhost:1123/fred.bloggs", :referer => "/diary"
assert_response :redirect
res = openid_request(@response.redirect_url)
post "/login", res
assert_redirected_to auth_path(:provider => "openid", :openid_url => "http://localhost:1123/fred.bloggs", :origin => "/login")
follow_redirect!
assert_response :redirect
assert_redirected_to auth_success_path(:provider => "openid", :openid_url => "http://localhost:1123/fred.bloggs", :origin => "/login")
follow_redirect!
assert_response :redirect
follow_redirect!
assert_response :success

View file

@ -142,42 +142,5 @@ module ActiveSupport
def assert_no_missing_translations(msg = "")
assert_select "span[class=translation_missing]", false, "Missing translation #{msg}"
end
# Set things up for OpenID testing
def openid_setup
Net::HTTP.get_response(URI.parse("http://localhost:1123/"))
rescue
# It isn't, so start a new instance.
rots = IO.popen("#{Rails.root}/vendor/gems/rots-0.2.1/bin/rots --silent")
# Wait for up to 30 seconds for the server to start and respond before continuing
1.upto(30).each do
begin
sleep 1
Net::HTTP.get_response(URI.parse("http://localhost:1123/"))
# If the rescue block doesn't fire, ROTS is up and running and we can continue
break
rescue
# If the connection failed, do nothing and repeat the loop
next
end
end
# Arrange to kill the process when we exit - note that we need
# to kill it really har due to a bug in ROTS
Kernel.at_exit do
Process.kill("KILL", rots.pid)
end
end
def openid_request(openid_request_uri)
openid_response = Net::HTTP.get_response(URI.parse(openid_request_uri))
openid_response_uri = URI(openid_response["Location"])
openid_response_qs = Rack::Utils.parse_query(openid_response_uri.query)
openid_response_qs
end
# Add more helper methods to be used by all tests here...
end
end

View file

@ -1,112 +0,0 @@
--- !ruby/object:Gem::Specification
name: rots
version: !ruby/object:Gem::Version
prerelease: false
segments:
- 0
- 2
- 1
version: 0.2.1
platform: ruby
authors:
- Roman Gonzalez
autorequire:
bindir: bin
cert_chain: []
date: 2010-05-11 00:00:00 +01:00
default_executable: rots
dependencies:
- !ruby/object:Gem::Dependency
name: rspec
prerelease: false
requirement: &id001 !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
type: :development
version_requirements: *id001
- !ruby/object:Gem::Dependency
name: rack
prerelease: false
requirement: &id002 !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
type: :development
version_requirements: *id002
- !ruby/object:Gem::Dependency
name: ruby-openid
prerelease: false
requirement: &id003 !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
type: :development
version_requirements: *id003
description: |
Ruby OpenID Test Server (ROST) provides a basic OpenID server made in top of the Rack gem.
With this small server, you can make dummy OpenID request for testing purposes,
the success of the response will depend on a parameter given on the url of the authentication request.
email: romanandreg@gmail.com
executables:
- rots
extensions: []
extra_rdoc_files:
- README
files:
- AUTHORS
- README
- Rakefile
- bin/rots
- lib/rots.rb
- lib/rots/identity_page_app.rb
- lib/rots/server_app.rb
- lib/rots/test_helper.rb
- rots.gemspec
- spec/server_app_spec.rb
- spec/spec_helper.rb
has_rdoc: true
homepage: http://github.com/roman
licenses: []
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ">="
- !ruby/object:Gem::Version
segments:
- 0
version: "0"
requirements: []
rubyforge_project: rots
rubygems_version: 1.3.6
signing_key:
specification_version: 3
summary: an OpenID server for making tests of OpenID clients implementations
test_files:
- spec/server_app_spec.rb
- spec/spec_helper.rb

View file

@ -1,2 +0,0 @@
* Roman Gonzalez <romanandreg@gmail.com>
* Anibal Rojas <anibal@rojas.net.ve>

View file

@ -1,64 +0,0 @@
= Ruby OpenID Test Server (ROTS), a dummy OpenID server that makes consumer tests dead easy.
ROTS is a minimal implementation of an OpenID server, developed on top of the Rack middleware, this
server provides an easy to use interface to make testing OpenID consumers really easy.
== No more mocks
Have you always wanted to test the authentication of an OpenID consumer implementation, but find your self
in a point where is to hard to mock? A lot of people have been there.
With ROTS, you only need to specify an identity url provided by the dummy server, passing with it a flag
saying that you want the authentication to be successful. It handles SREG extensions as well.
== How does it works
When you install the ROTS gem, a binary called rots is provided for starting the server (for more
info about what options you have when executing this file, check the -h option).
By default, rots will have a test user called "John Doe", with an OpenID identity "john.doe".
If you want to use your own test user name, you can specify a config file to rots. The
default configuration file looks like this:
# Default configuration file
identity: john.doe
sreg:
nickname: jdoe
fullname: John Doe
email: jhon@doe.com
dob: 1985-09-21
gender: M
You can specify a new config file using the option --config.
== Getting Started
The best way to get started, is running the rots server, and then starting to execute your OpenID consumer tests/specs. You just have to specify the identity url of your test user, if you want the OpenID response be successful just add the openid.success=true flag to the user identity url. If you don't specify the flag it
will return a cancel response instead.
Example:
it "should authenticate with OpenID" do
post("/consumer_openid_login", 'identity_url' => 'http://localhost:1132/john.doe?openid.success=true')
end
== Copyright
Copyright (C) 2009 Roman Gonzalez <romanandreg@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,125 +0,0 @@
# Rakefile for Rack. -*-ruby-*-
require 'rake/rdoctask'
require 'rake/testtask'
require 'spec/rake/spectask'
desc "Run all the tests"
task :default => [:spec]
desc "Do predistribution stuff"
task :predist => [:changelog, :rdoc]
desc "Make an archive as .tar.gz"
task :dist => [:fulltest, :predist] do
sh "git archive --format=tar --prefix=#{release}/ HEAD^{tree} >#{release}.tar"
sh "pax -waf #{release}.tar -s ':^:#{release}/:' RDOX SPEC ChangeLog doc"
sh "gzip -f -9 #{release}.tar"
end
# Helper to retrieve the "revision number" of the git tree.
def git_tree_version
#if File.directory?(".git")
# @tree_version ||= `git describe`.strip.sub('-', '.')
# @tree_version << ".0" unless @tree_version.count('.') == 2
#else
$: << "lib"
require 'rots'
@tree_version = Rots.release
#end
@tree_version
end
def gem_version
git_tree_version.gsub(/-.*/, '')
end
def release
"ruby-openid-tester-#{git_tree_version}"
end
def manifest
`git ls-files`.split("\n")
end
desc "Generate a ChangeLog"
task :changelog do
File.open("ChangeLog", "w") do |out|
`git log -z`.split("\0").map do |chunk|
author = chunk[/Author: (.*)/, 1].strip
date = chunk[/Date: (.*)/, 1].strip
desc, detail = $'.strip.split("\n", 2)
detail ||= ""
detail.rstrip!
out.puts "#{date} #{author}"
out.puts " * #{desc.strip}"
out.puts detail unless detail.empty?
out.puts
end
end
end
begin
require 'rubygems'
require 'rake'
require 'rake/clean'
require 'rake/packagetask'
require 'rake/gempackagetask'
require 'fileutils'
rescue LoadError
# Too bad.
else
spec = Gem::Specification.new do |s|
s.name = "rots"
s.version = gem_version
s.platform = Gem::Platform::RUBY
s.summary = "an OpenID server for making tests of OpenID clients implementations"
s.description = <<-EOF
Ruby OpenID Test Server (ROST) provides a basic OpenID server made in top of the Rack gem.
With this small server, you can make dummy OpenID request for testing purposes,
the success of the response will depend on a parameter given on the url of the authentication request.
EOF
s.files = manifest
s.bindir = 'bin'
s.executables << 'rots'
s.require_path = 'lib'
s.has_rdoc = true
s.extra_rdoc_files = ['README']
s.test_files = Dir['spec/*_spec.rb']
s.author = 'Roman Gonzalez'
s.email = 'romanandreg@gmail.com'
s.homepage = 'http://github.com/roman'
s.rubyforge_project = 'rots'
s.add_development_dependency 'rspec'
s.add_development_dependency 'rack'
s.add_development_dependency 'ruby-openid', '~> 2.0.0'
end
Rake::GemPackageTask.new(spec) do |p|
p.gem_spec = spec
p.need_tar = false
p.need_zip = false
end
end
Spec::Rake::SpecTask.new do |t|
end
desc "Generate RDoc documentation"
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.options << '--line-numbers' << '--inline-source' <<
'--main' << 'README' <<
'--title' << 'ROTS Documentation' <<
'--charset' << 'utf-8'
rdoc.rdoc_dir = "doc"
rdoc.rdoc_files.include 'README'
rdoc.rdoc_files.include('lib/ruby_openid_test_server.rb')
rdoc.rdoc_files.include('lib/ruby_openid_test_server/*.rb')
end

View file

@ -1,99 +0,0 @@
#!/usr/bin/env ruby
# -*- ruby -*-
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require "rubygems"
require "optparse"
require "rack"
require "yaml"
require "rots"
server_options = {
:debugger => false,
:port => 1123,
:verbose => true,
:storage => File.join('.', 'tmp', 'rots'),
:config => <<-DEFAULT_CONFIG
# Default configuration file
identity: john.doe
sreg:
nickname: jdoe
fullname: John Doe
email: jhon@doe.com
dob: 1985-09-21
gender: M
DEFAULT_CONFIG
}
opts = OptionParser.new do |opts|
opts.banner = "Usage: rots [options]"
opts.separator ""
opts.separator "Options:"
opts.on("-p", "--port PORT",
"use PORT (default: 1123)") do |port|
server_options[:port] = port
end
opts.on("-s", "--storage PATH",
"use PATH as the OpenID Server storage path (default: ./tmp/rots)") do |storage_path|
server_options[:storage] = storage_path
end
opts.on("-c", "--config FILE.yaml",
"server configuration YAML file") do |config_path|
abort "\x1B[31mConfiguration file #{config_path} not found\x1B[0m" unless File.exists?(config_path)
server_options[:config] = File.new(config_path)
end
opts.on("-s", "--silent",
"If specified, the server will be in silent mode") do
server_options[:verbose] = false
end
opts.on("-d", "--debugger") do
server_options[:debugger] = true
end
opts.separator ""
opts.separator "Common options:"
opts.on_tail("-h", "--help", "Show this help message") do
puts opts
exit
end
end
opts.parse!(ARGV)
config = YAML.load(server_options[:config])
require "ruby-debug" if server_options[:debugger]
server = Rack::Builder.new do
use Rack::Lint
if server_options[:verbose]
use Rack::CommonLogger, STDOUT
use Rack::ShowExceptions
end
map ("/%s" % config['identity']) do
run Rots::IdentityPageApp.new(config, server_options)
end
map "/server" do
run Rots::ServerApp.new(config, server_options)
end
end
puts "\x1B[32mRunning OpenID Test server on port 1123\x1B[0m" if server_options[:verbose]
begin
Rack::Handler::Mongrel.run server, :Port => server_options[:port]
rescue LoadError
if server_options[:verbose]
Rack::Handler::WEBrick.run server, :Port => server_options[:port]
else
Rack::Handler::WEBrick.run server, :Port => server_options[:port], :AccessLog => [], :Logger => WEBrick::Log::new("/dev/null", 7)
end
end

View file

@ -1,11 +0,0 @@
module Rots
def self.release
"0.2.1"
end
end
require "rots/server_app"
require "rots/identity_page_app"
require "rots/test_helper"

View file

@ -1,36 +0,0 @@
require 'rack/request'
require 'rack/response'
require 'rack/utils'
require 'openid'
class Rots::IdentityPageApp
def initialize(config, server_options)
@server_options = server_options
@config = config
end
def call(env)
@request = Rack::Request.new(env)
Rack::Response.new do |response|
response.write <<-HERE
<html>
<head>
<link rel="openid2.provider" href="#{op_endpoint}" />
<link rel="openid.server" href="#{op_endpoint}" />
</head>
<body>
<h1>This is #{@config['identity']} identity page</h1>
</body>
</html>
HERE
end.finish
end
def op_endpoint
"http://%s:%d/server/%s" % [@request.host,
@request.port,
(@request.params['openid.success'] ? '?openid.success=true' : '')]
end
end

View file

@ -1,147 +0,0 @@
require 'openid'
require 'openid/extension'
require 'openid/extensions/sreg'
require 'openid/store/filesystem'
require 'openid/util'
require 'rack/request'
require 'rack/utils'
require 'fileutils'
module Rots
class ServerApp
attr_accessor :request,:openid_request,
:response, :openid_response,
:server
def initialize(config, server_options)
@server_options = server_options
@sreg_fields = config['sreg']
end
def call(env)
on_openid_request(env) do
if !is_checkid_request?
@openid_response = @server.handle_request(@openid_request)
reply_consumer
elsif is_checkid_immediate?
process_immediate_checkid_request
else
process_checkid_request
end
end
end
protected
def on_openid_request(env)
create_wrappers(env)
if @openid_request.nil?
[200, {'Content-Type' => 'text/html'},
["<html><body><h1>ROTS => This is an OpenID endpoint</h1></body></html>"] ]
else
yield
end
end
def create_wrappers(env)
@request = Rack::Request.new(env)
@server = OpenID::Server::Server.new(storage, op_endpoint)
@openid_request = @server.decode_request(@request.params)
@openid_sreg_request = OpenID::SReg::Request.from_openid_request(@openid_request) unless @openid_request.nil?
end
def is_checkid_request?
@openid_request.is_a?(OpenID::Server::CheckIDRequest)
end
def is_checkid_immediate?
@openid_request && @openid_request.immediate
end
def process_immediate_checkid_request
# TODO: We should enable the user to configure
# if she wants immediate request support or not
url = OpenID::Util.append_args(@openid_request.return_to,
@request.params.merge('openid.mode' => 'setup_needed'))
redirect(url)
end
def process_checkid_request
if checkid_request_is_valid?
return_successful_openid_response
else
return_cancel_openid_response
end
end
def checkid_request_is_valid?
@request.params['openid.success'] == 'true'
end
def return_successful_openid_response
@openid_response = @openid_request.answer(true)
process_sreg_extension
# TODO: Add support for SREG extension
@server.signatory.sign(@openid_response) if @openid_response.needs_signing
reply_consumer
end
def process_sreg_extension
return if @openid_sreg_request.nil?
response = OpenID::SReg::Response.extract_response(@openid_sreg_request, @sreg_fields)
@openid_response.add_extension(response)
end
def return_cancel_openid_response
redirect(@openid_request.cancel_url)
end
def reply_consumer
web_response = @server.encode_response(@openid_response)
case web_response.code
when OpenID::Server::HTTP_OK
success(web_response.body)
when OpenID::Server::HTTP_REDIRECT
redirect(web_response.headers['location'])
else
bad_request
end
end
def redirect(uri)
[ 303, {'Content-Length'=>'0', 'Content-Type'=>'text/plain',
'Location' => uri},
[] ]
end
def bad_request()
[ 400, {'Content-Type'=>'text/plain', 'Content-Length'=>'0'},
[] ]
end
def storage
# create the folder if it doesn't exist
FileUtils.mkdir_p(@server_options[:storage]) unless File.exist?(@server_options[:storage])
OpenID::Store::Filesystem.new(@server_options[:storage])
end
def success(text="")
Rack::Response.new(text).finish
end
def op_endpoint
if @request.url =~ /(.*\?openid.success=true)/
$1
elsif @request.url =~ /([^?]*)/
$1
else
nil
end
end
end
end

View file

@ -1,16 +0,0 @@
require "openid/consumer"
require "openid/consumer/checkid_request.rb"
require "net/http"
module Rots::TestHelper
def openid_request(openid_request_uri)
openid_response = Net::HTTP.get_response(URI.parse(openid_request_uri))
openid_response_uri = URI(openid_response['Location'])
openid_response_qs = Rack::Utils.parse_query(openid_response_uri.query)
{ :url => openid_response_uri.to_s,
:query_params => openid_response_qs }
end
end

View file

@ -1,31 +0,0 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = "rots"
s.version = '0.2.1'
s.platform = Gem::Platform::RUBY
s.summary = "an OpenID server for making tests of OpenID clients implementations"
s.description = <<-EOF
Ruby OpenID Test Server (ROST) provides a basic OpenID server made in top of the Rack gem.
With this small server, you can make dummy OpenID request for testing purposes,
the success of the response will depend on a parameter given on the url of the authentication request.
EOF
s.files = ["AUTHORS", "README", "Rakefile", "bin/rots", "lib/rots.rb", "lib/rots/identity_page_app.rb", "lib/rots/server_app.rb", "lib/rots/test_helper.rb","rots.gemspec", "spec/server_app_spec.rb", "spec/spec_helper.rb"]
s.bindir = 'bin'
s.executables << 'rots'
s.require_path = 'lib'
s.has_rdoc = true
s.extra_rdoc_files = ['README']
s.test_files = ['spec/server_app_spec.rb', 'spec/spec_helper.rb']
s.author = 'Roman Gonzalez'
s.email = 'romanandreg@gmail.com'
s.homepage = 'http://github.com/roman'
s.rubyforge_project = 'rots'
s.add_development_dependency 'rspec'
s.add_development_dependency 'rack'
s.add_development_dependency 'ruby-openid'
end

View file

@ -1,99 +0,0 @@
require File.join(File.dirname(__FILE__), 'spec_helper')
# This is just a comment test
describe Rots::ServerApp do
describe "when the request is not an OpenID request" do
it "should return a helpful message saying that is an OpenID endpoint" do
request = Rack::MockRequest.new(Rots::ServerApp.new({'sreg' => {}},
{:storage => File.join(*%w(. tmp rots)) }))
response = request.get("/")
response.should be_ok
response.body.should == "<html><body><h1>ROTS => This is an OpenID endpoint</h1></body></html>"
end
end
describe "when the request is an OpenID request" do
before(:each) do
@request = Rack::MockRequest.new(Rots::ServerApp.new({
'identity' => 'john.doe',
'sreg' => {
'email' => "john@doe.com",
'nickname' => 'johndoe',
'fullname' => "John Doe",
'dob' => "1985-09-21",
'gender' => "M"
}},
{:storage => File.join(*%w(. tmp rots))}
))
end
describe "and it is a check_id request" do
describe "and is immediate" do
it "should return an openid.mode equal to setup_needed" do
response = checkid_immediate(@request)
params = openid_params(response)
params['openid.mode'].should == 'setup_needed'
end
end
describe "and is not immediate" do
describe "with a success flag" do
it "should return an openid.mode equal to id_res" do
response = checkid_setup(@request, 'openid.success' => 'true')
params = openid_params(response)
params['openid.mode'].should == 'id_res'
end
end
describe "without a success flag" do
it "should return an openid.mode equal to cancel" do
response = checkid_setup(@request)
params = openid_params(response)
params['openid.mode'].should == 'cancel'
end
end
describe "using SREG extension with a success flag" do
it "should return an openid.mode equal to id_res" do
response = checkid_setup(@request, 'openid.success' => 'true')
params = openid_params(response)
params['openid.mode'].should == 'id_res'
end
it "should return all the sreg fields" do
response = checkid_setup(@request, {
'openid.success' => true,
'openid.ns.sreg' => OpenID::SReg::NS_URI,
'openid.sreg.required' => 'email,nickname,fullname',
'openid.sreg.optional' => 'dob,gender'
})
params = openid_params(response)
params['openid.sreg.email'].should == "john@doe.com"
params['openid.sreg.nickname'].should == 'johndoe'
params['openid.sreg.fullname'].should == "John Doe"
params['openid.sreg.dob'].should == "1985-09-21"
params['openid.sreg.gender'].should == "M"
end
end
end
end
end
end

View file

@ -1,73 +0,0 @@
$:.unshift(File.dirname(__FILE__), '..', 'lib')
require "rubygems"
require "spec"
require "rack"
require "rots"
module Rots::RequestHelper
def checkid_setup(request, params={}, with_associate=true)
assoc_handle = make_association(request) if with_associate
send_checkid(request, :setup, params, assoc_handle)
end
def checkid_immediate(request, params={}, with_associate=true)
assoc_handle = make_association(request) if with_associate
send_checkid(request, :immediate, params, assoc_handle)
end
def openid_params(response)
uri = URI(response.headers['Location'])
Rack::Utils.parse_query(uri.query)
end
protected
def send_checkid(request, mode, params={}, assoc_handle = nil)
params = self.send(:"checkid_#{mode}_params", params)
params.merge('openid.assoc_handle' => assoc_handle) if assoc_handle
qs = "/?" + Rack::Utils.build_query(params)
request.get(qs)
end
def make_association(request)
associate_qs = Rack::Utils.build_query(associate_params)
response = request.post('/', :input => associate_qs)
parse_assoc_handle_from(response)
end
def parse_assoc_handle_from(response)
response.body.split("\n")[0].match(/^assoc_handle:(.*)$/).captures[0]
end
def checkid_setup_params(params = {})
{
"openid.ns" => "http://specs.openid.net/auth/2.0",
"openid.mode" => "checkid_setup",
"openid.claimed_id" => 'john.doe',
"openid.identity" => 'john.doe',
"openid.return_to" => "http://www.google.com"
# need to specify the openid_handle by hand
}.merge!(params)
end
def checkid_immediate_params(params = {})
checkid_setup_params({'openid.mode' => 'checkid_immediate'}.merge!(params))
end
def associate_params
{
"openid.ns" => "http://specs.openid.net/auth/2.0",
"openid.mode" => "associate",
"openid.session_type" => "DH-SHA1",
"openid.assoc_type" => "HMAC-SHA1",
"openid.dh_consumer_public" =>
"U672/RsDUNxAFFAXA+ShVh5LMD2CRdsoqdqhDCPUzfCNy2f44uTWuid/MZuGfJmiVA7QmxqM3GSb8EVq3SGK8eGEwwyzUtatqHidx72rfwAav5AUrZTnwSPQJyiCFrKNGmNhXdRJzcfzSkgaC3hVz2kpADzEevIExG6agns1sYY="
}
end
end
Spec::Runner.configure do |config|
config.include Rots::RequestHelper
end