rots 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 172f3bd6eee16ac007608e427e6dac75ddab29657cdb701c6bce562a1959f66d
4
+ data.tar.gz: 386ee12b9e29481d6c7a3c063e730510bf2e5718d89b3aedf3211d37fefd4ea9
5
+ SHA512:
6
+ metadata.gz: e2610b68941ba6da18d9e1b189aa4341bbb17b37d38e18912c0ea5ee121e42f1cc1cd96eb9338170db8af09cedb90aabe4bdd63064432cc3117b1be9e3c50586
7
+ data.tar.gz: 65f012defce46b5ebad95bc43bc7820a7843b10de6cc7e167c26d65aae679d3789b6b7b5170492ce16feb0f216f9623fb58bb19a6c57a11c9576915f45f1d6f7
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ ;5�00c\��'��D+���X
2
+ �j��?�=�Kb����l�d�p�)�='Y(����*�v�+��)ѣBc4�*@)֑�5i6�B��'�z�&3�FF=1�{�wdR���f���WnB%��F'.�0�Tu<�)+@b�:�׍���@�hǩ�K�
3
+ �q� ?\�~���Y�%>x���5t����;��|[ڹ�^4ƙ��QW+�y�X޲�d��wE3z]<d��M�֬��)N���ڕ��>q���.t^
data/AUTHORS ADDED
@@ -0,0 +1,4 @@
1
+ * Roman Gonzalez <romanandreg@gmail.com>
2
+ * Anibal Rojas <anibal@rojas.net.ve>
3
+ * Tom Quackenbush <tquackenbush@agoragames.com>
4
+ * Peter Boling <peter.boling@gmail.com>
data/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ Since version 3.0.0, the format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+ ### Added
9
+ ### Changed
10
+ ### Fixed
11
+ ### Removed
12
+
13
+ ## 1.0.0 - 2024-09-24
14
+ COVERAGE: 96.33% -- 236/245 lines in 11 files
15
+ BRANCH COVERAGE: 77.78% -- 35/45 branches in 11 files
16
+ 37.84% documented
17
+ ### Fixed
18
+ - More tests & switch to RSpec
19
+ - Modernized code (require_relative)
20
+ - Refactored
21
+ - GitHub Actions for CI
22
+ - Upgraded to ruby-openid2 v3.1.0
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,55 @@
1
+ ## Contributing
2
+
3
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/oauth-xx/rots][🚎src-main]
4
+ . This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to
5
+ the [code of conduct][🤝conduct].
6
+
7
+ To submit a patch, please fork the project and create a patch with tests.
8
+ Once you're happy with it send a pull request.
9
+
10
+ ## Release
11
+
12
+ ### One-time, Per-developer, Setup
13
+
14
+ **IMPORTANT**: Your public key for signing gems will need to be picked up by the line in the
15
+ `gemspec` defining the `spec.cert_chain` (check the relevant ENV variables there),
16
+ in order to sign the new release.
17
+ See: [RubyGems Security Guide][🔒️rubygems-security-guide]
18
+
19
+ ### To release a new version:
20
+
21
+ 1. Run `bin/setup && bin/rake` as a tests, coverage, & linting sanity check
22
+ 2. Update the version number in `version.rb`
23
+ 3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock`
24
+ 4. Run `git commit -am "🔖 Prepare release v<VERSION>"` to commit the changes
25
+ 5. Run `git push` to trigger the final CI pipeline before release, & merge PRs
26
+ - NOTE: Remember to [check the build][🧪build]!
27
+ 6. Run `export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME`
28
+ 7. Run `git checkout $GIT_TRUNK_BRANCH_NAME`
29
+ 8. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure you will release the latest trunk code
30
+ 9. Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use same timestamp, and generate same checksums
31
+ - Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH`
32
+ - If the echo above has no output, then it didn't work.
33
+ - Note that you'll need the `zsh/datetime` module, if running `zsh`.
34
+ - In `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH`
35
+ 10. Run `bundle exec rake build`
36
+ 11. Run `bin/checksums` (more [context][🔒️rubygems-checksums-pr]) to create SHA-256 and SHA-512 checksums
37
+ - Checksums will be committed automatically by the script, but not pushed
38
+ 12. Run `bundle exec rake release` which will create a git tag for the version,
39
+ push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems]
40
+
41
+ ## Contributors
42
+
43
+ [![Contributors][🖐contributors-img]][🖐contributors]
44
+
45
+ Made with [contributors-img][🖐contrib-rocks].
46
+
47
+ [🧪build]: https://github.com/oauth-xx/rots/actions
48
+ [🤝conduct]: https://github.com/oauth-xx/rots/blob/main/CODE_OF_CONDUCT.md
49
+ [🖐contrib-rocks]: https://contrib.rocks
50
+ [🖐contributors]: https://github.com/oauth-xx/rots/graphs/contributors
51
+ [🖐contributors-img]: https://contrib.rocks/image?repo=oauth-xx/rots
52
+ [💎rubygems]: https://rubygems.org
53
+ [🔒️rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems
54
+ [🔒️rubygems-checksums-pr]: https://github.com/rubygems/guides/pull/325
55
+ [🚎src-main]: https://github.com/oauth-xx/rots
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2009 - 2011, 2013 - 2014, 2017 Roman Gonzalez <romanandreg@gmail.com>
4
+ Copyright (c) 2024 Peter H. Boling, http://railsbling.com
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to
8
+ deal in the Software without restriction, including without limitation the
9
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ sell copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,255 @@
1
+ # ROTS - Ruby OpenID Test Server
2
+
3
+ <div id="badges">
4
+
5
+ <div align="center">
6
+
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
8
+ [![Version](https://img.shields.io/gem/v/rots.svg)](https://rubygems.org/gems/rots)
9
+ [![Downloads Today](https://img.shields.io/gem/rd/rots.svg)](https://github.com/oauth-xx/rots)
10
+ [![CodeCov][🖇codecov-img♻️]][🖇codecov]
11
+ [![CI Supported Build][🚎s-wfi]][🚎s-wf]
12
+ [![CI Unsupported Build][🚎us-wfi]][🚎us-wf]
13
+ [![CI Style Build][🚎st-wfi]][🚎st-wf]
14
+ [![CI Coverage Build][🚎cov-wfi]][🚎cov-wf]
15
+ [![CI Heads Build][🚎hd-wfi]][🚎hd-wf]
16
+ [![CI Ancient Build][🚎an-wfi]][🚎an-wf]
17
+
18
+ [🖇codecov-img♻️]: https://codecov.io/gh/oauth-xx/rots/graph/badge.svg?token=qycnWzl6qM
19
+ [🖇codecov]: https://codecov.io/gh/oauth-xx/rots
20
+ [🚎s-wf]: https://github.com/oauth-xx/rots/actions/workflows/supported.yml
21
+ [🚎s-wfi]: https://github.com/oauth-xx/rots/actions/workflows/supported.yml/badge.svg
22
+ [🚎us-wf]: https://github.com/oauth-xx/rots/actions/workflows/unsupported.yml
23
+ [🚎us-wfi]: https://github.com/oauth-xx/rots/actions/workflows/unsupported.yml/badge.svg
24
+ [🚎st-wf]: https://github.com/oauth-xx/rots/actions/workflows/style.yml
25
+ [🚎st-wfi]: https://github.com/oauth-xx/rots/actions/workflows/style.yml/badge.svg
26
+ [🚎cov-wf]: https://github.com/oauth-xx/rots/actions/workflows/coverage.yml
27
+ [🚎cov-wfi]: https://github.com/oauth-xx/rots/actions/workflows/coverage.yml/badge.svg
28
+ [🚎hd-wf]: https://github.com/oauth-xx/rots/actions/workflows/heads.yml
29
+ [🚎hd-wfi]: https://github.com/oauth-xx/rots/actions/workflows/heads.yml/badge.svg
30
+ [🚎an-wf]: https://github.com/oauth-xx/rots/actions/workflows/ancient.yml
31
+ [🚎an-wfi]: https://github.com/oauth-xx/rots/actions/workflows/ancient.yml/badge.svg
32
+
33
+ </div>
34
+
35
+ -----
36
+
37
+ <div align="center">
38
+
39
+ [![Liberapay Patrons][⛳liberapay-img]][⛳liberapay]
40
+ [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor]
41
+ [![Polar Shield][🖇polar-img]][🖇polar]
42
+ [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi]
43
+ [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon]
44
+
45
+ [⛳liberapay-img]: https://img.shields.io/liberapay/patrons/pboling.svg?logo=liberapay
46
+ [⛳liberapay]: https://liberapay.com/pboling/donate
47
+ [🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github
48
+ [🖇sponsor]: https://github.com/sponsors/pboling
49
+ [🖇polar-img]: https://polar.sh/embed/seeks-funding-shield.svg?org=pboling
50
+ [🖇polar]: https://polar.sh/pboling
51
+ [🖇kofi-img]: https://img.shields.io/badge/buy%20me%20coffee-donate-yellow.svg
52
+ [🖇kofi]: https://ko-fi.com/O5O86SNP4
53
+ [🖇patreon-img]: https://img.shields.io/badge/patreon-donate-yellow.svg
54
+ [🖇patreon]: https://patreon.com/galtzo
55
+
56
+ <span class="badge-buymealatte">
57
+ <a href="https://www.buymeacoffee.com/pboling"><img src="https://img.buymeacoffee.com/button-api/?text=Buy me a latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" /></a>
58
+ </span>
59
+
60
+ </div>
61
+ </div>
62
+
63
+ Ruby OpenID Test Server (ROTS) is a dummy OpenID server that makes consumer tests dead easy.
64
+
65
+ ROTS is a minimal implementation of an OpenID server, developed on top of the Rack middleware, this
66
+ server provides an easy to use interface to make testing OpenID consumers really easy.
67
+
68
+ ## No more mocks
69
+
70
+ Have you always wanted to test the authentication of an OpenID consumer implementation, but find your self
71
+ in a point where is to hard to mock? A lot of people have been there.
72
+
73
+ With ROTS, you only need to specify an identity url provided by the dummy server, passing with it a flag
74
+ saying that you want the authentication to be successful. It handles SREG extensions as well.
75
+
76
+ ### Or do use mocks, maybe?
77
+
78
+ You can also require a library of mocks and request helpers which might be useful in your tests (perhaps in your `spec_helper.rb`):
79
+
80
+ ```ruby
81
+ require "rots/mocks"
82
+ require "rots/test"
83
+
84
+ OpenID.fetcher = Rots::Mocks::Fetcher.new(Rots::Mocks::RotsServer.new)
85
+
86
+ RSpec.configure do |config|
87
+ config.include(Rots::Test::RackTestHelpers)
88
+ end
89
+ ```
90
+
91
+ Helpers are written with minitest syntax,
92
+ but RSpec supports that, so it should work in both RSpec and MiniTest,
93
+ and you don't need to switch your other tests to use minitest syntax.
94
+ Use them interchangeably, as needed.
95
+ ```ruby
96
+ RSpec.configure do |config|
97
+ config.expect_with(:rspec, :minitest)
98
+ end
99
+ ```
100
+
101
+ And in another file (see `spec/rots/mocks/integration_spec.rb` for more):
102
+
103
+ ```ruby
104
+ RSpec.describe("openid") do
105
+ subject(:app) { Rots::Mocks::ClientApp.new(**options) }
106
+
107
+ let(:options) { {identifier: "#{Rots::Mocks::RotsServer::SERVER_URL}/john.doe?openid.success=true"} }
108
+
109
+ it "with_get" do
110
+ mock_openid_request(app, "/", method: "GET")
111
+ follow_openid_redirect!(app)
112
+
113
+ assert_equal 200, @response.status
114
+ assert_equal "GET", @response.headers["X-Method"]
115
+ assert_equal "/", @response.headers["X-Path"]
116
+ assert_equal "success", @response.body
117
+ end
118
+ end
119
+ ```
120
+
121
+ ### Note about the deprecation of stdlib gems `logger`, `rexml`, `stringio`, `net-http`, and `uri`
122
+
123
+ They will not be direct dependencies until the situation with bundler is resolved.
124
+ You will need to add them directly to downstream tools.
125
+
126
+ See [this discussion](https://github.com/rubygems/rubygems/issues/7178#issuecomment-2372558363) for more information.
127
+
128
+ ## How does it work?
129
+
130
+ When you install the ROTS gem, a binary called rots is provided for starting the server (for more
131
+ info about what options you have when executing this file, check the -h option).
132
+
133
+ By default, rots will have a test user called "John Doe", with an OpenID identity "john.doe".
134
+ If you want to use your own test user name, you can specify a config file to rots. The
135
+ default configuration file looks like this:
136
+
137
+ ### Default configuration file
138
+ ```yaml
139
+ identity: john.doe
140
+ sreg:
141
+ nickname: jdoe
142
+ fullname: John Doe
143
+ email: jhon@doe.com
144
+ dob: 1985-09-21
145
+ gender: M
146
+ ```
147
+
148
+ You can specify a new config file using the option `--config`.
149
+
150
+ ## Getting Started
151
+
152
+ 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
153
+ will return a cancel response instead.
154
+
155
+ Example:
156
+ ```ruby
157
+ it "should authenticate with OpenID" do
158
+ post("/consumer_openid_login", "identity_url" => "http://localhost:1132/john.doe?openid.success=true")
159
+ end
160
+ ```
161
+
162
+ ## 🤝 Contributing
163
+
164
+ See [CONTRIBUTING.md][🤝contributing]
165
+
166
+ [🤝contributing]: CONTRIBUTING.md
167
+
168
+ ### Code Coverage
169
+
170
+ If you need some ideas of where to help, you could work on adding more code coverage.
171
+
172
+ [![Coverage Graph][🔑codecov-g]][🖇codecov]
173
+
174
+ [🔑codecov-g]: https://codecov.io/gh/oauth-xx/rots/graphs/tree.svg?token=qycnWzl6qM
175
+
176
+ ## 🌈 Contributors
177
+
178
+ [![Contributors][🖐contributors-img]][🖐contributors]
179
+
180
+ Made with [contributors-img][🖐contrib-rocks].
181
+
182
+ [🖐contrib-rocks]: https://contrib.rocks
183
+ [🖐contributors]: https://github.com/oauth-xx/rots/graphs/contributors
184
+ [🖐contributors-img]: https://contrib.rocks/image?repo=oauth-xx/rots
185
+
186
+ ## Star History
187
+
188
+ <a href="https://star-history.com/#oauth-xx/rots&Date">
189
+ <picture>
190
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=oauth-xx/rots&type=Date&theme=dark" />
191
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=oauth-xx/rots&type=Date" />
192
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=oauth-xx/rots&type=Date" />
193
+ </picture>
194
+ </a>
195
+
196
+ ## 🪇 Code of Conduct
197
+
198
+ Everyone interacting in this project's codebases, issue trackers,
199
+ chat rooms and mailing lists is expected to follow the [code of conduct][🪇conduct].
200
+
201
+ [🪇conduct]: CODE_OF_CONDUCT.md
202
+
203
+ ## 📌 Versioning
204
+
205
+ This Library adheres to [Semantic Versioning 2.0.0][📌semver].
206
+ Violations of this scheme should be reported as bugs.
207
+ Specifically, if a minor or patch version is released that breaks backward compatibility,
208
+ a new version should be immediately released that restores compatibility.
209
+ Breaking changes to the public API will only be introduced with new major versions.
210
+
211
+ To get a better understanding of how SemVer is intended to work over a project's lifetime,
212
+ read this article from the creator of SemVer:
213
+
214
+ - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred]
215
+
216
+ As a result of this policy, you can (and should) specify a dependency on these libraries using
217
+ the [Pessimistic Version Constraint][📌pvc] with two digits of precision.
218
+
219
+ For example:
220
+
221
+ ```ruby
222
+ spec.add_dependency("rots", "~> 1.0")
223
+ ```
224
+
225
+ See [CHANGELOG.md][📌changelog] for list of releases.
226
+
227
+ [comment]: <> ( 📌 VERSIONING LINKS )
228
+
229
+ [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint
230
+ [📌semver]: http://semver.org/
231
+ [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html
232
+ [📌changelog]: CHANGELOG.md
233
+
234
+ ## 📄 License
235
+
236
+ The gem is available as open source under the terms of
237
+ the [MIT License][📄license] [![License: MIT][📄license-img]][📄license-ref].
238
+ See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright-notice-explainer].
239
+
240
+ [comment]: <> ( 📄 LEGAL LINKS )
241
+
242
+ [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
243
+ [📄license]: LICENSE.txt
244
+ [📄license-ref]: https://opensource.org/licenses/MIT
245
+ [📄license-img]: https://img.shields.io/badge/License-MIT-green.svg
246
+
247
+ ### © Copyright
248
+
249
+ * Copyright (c) 2013 - 2014, 2016 - 2020, 2023 - 2024 [Peter H. Boling][peterboling] of [Rails Bling][railsbling]
250
+
251
+ [railsbling]: http://www.railsbling.com
252
+ [peterboling]: http://www.peterboling.com
253
+ [bundle-group-pattern]: https://gist.github.com/pboling/4564780
254
+ [documentation]: http://rdoc.info/github/oauth-xx/rots/frames
255
+ [homepage]: https://github.com/oauth-xx/rots
data/SECURITY.md ADDED
@@ -0,0 +1,14 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ |---------|-----------|
7
+ | 1.x | ✅ |
8
+ | 0.x | ❌ |
9
+
10
+ ## Reporting a Vulnerability
11
+
12
+ Peter Boling is the primary maintainer of this gem. Please find a way
13
+ to [contact him directly](https://railsbling.com/contact) to report the issue. Include as much relevant information as
14
+ possible.
data/exe/rots ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+
4
+ require "rots"
5
+
6
+ server_options = {
7
+ debugger: false,
8
+ port: 1123,
9
+ verbose: true,
10
+ storage: File.join(".", "tmp", "rots"),
11
+ config: <<~DEFAULT_CONFIG,
12
+ # Default configuration file
13
+ identity: john.doe
14
+ sreg:
15
+ nickname: jdoe
16
+ fullname: John Doe
17
+ email: jhon@doe.com
18
+ dob: 1985-09-21
19
+ gender: M
20
+
21
+ DEFAULT_CONFIG
22
+ }
23
+
24
+ opts = OptionParser.new do |opts|
25
+ opts.banner = "Usage: rots [options]"
26
+
27
+ opts.separator("")
28
+ opts.separator("Options:")
29
+
30
+ opts.on(
31
+ "-p",
32
+ "--port PORT",
33
+ "use PORT (default: 1123)",
34
+ ) do |port|
35
+ server_options[:port] = port
36
+ end
37
+
38
+ opts.on(
39
+ "-s",
40
+ "--storage PATH",
41
+ "use PATH as the OpenID Server storage path (default: ./tmp/rots)",
42
+ ) do |storage_path|
43
+ server_options[:storage] = storage_path
44
+ end
45
+
46
+ opts.on(
47
+ "-c",
48
+ "--config FILE.yaml",
49
+ "server configuration YAML file",
50
+ ) do |config_path|
51
+ abort("\x1B[31mConfiguration file #{config_path} not found\x1B[0m") unless File.exist?(config_path)
52
+ server_options[:config] = File.new(config_path)
53
+ end
54
+
55
+ opts.on(
56
+ "-s",
57
+ "--silent",
58
+ "If specified, the server will be in silent mode",
59
+ ) do
60
+ server_options[:verbose] = false
61
+ end
62
+
63
+ opts.on("-d", "--debugger") do
64
+ server_options[:debugger] = true
65
+ end
66
+
67
+ opts.separator("")
68
+ opts.separator("Common options:")
69
+
70
+ opts.on_tail("-h", "--help", "Show this help message") do
71
+ puts opts
72
+ exit
73
+ end
74
+ end
75
+
76
+ opts.parse!(ARGV)
77
+
78
+ config = YAML.load(server_options[:config], permitted_classes: [Date])
79
+
80
+ require "ruby-debug" if server_options[:debugger]
81
+
82
+ server = Rack::Builder.new do
83
+ use(Rack::Lint)
84
+ if server_options[:verbose]
85
+ use(Rack::CommonLogger, $stdout)
86
+ use(Rack::ShowExceptions)
87
+ end
88
+ map("/%s" % config["identity"]) do
89
+ run(Rots::IdentityPageApp.new(config, server_options))
90
+ end
91
+ map("/server") do
92
+ run(Rots::ServerApp.new(config, server_options))
93
+ end
94
+ end
95
+
96
+ puts "\x1B[32mRunning Ruby OpenID Test Server (ROTS) on port #{server_options[:port]}\x1B[0m" if server_options[:verbose]
97
+
98
+ Rackup::Server.start(app: server, Port: server_options[:port])
@@ -0,0 +1,37 @@
1
+ # external libraries
2
+ require "rack/request"
3
+ require "rack/response"
4
+ require "rack/utils"
5
+ require "openid"
6
+
7
+ class Rots::IdentityPageApp
8
+ def initialize(config, server_options)
9
+ @server_options = server_options
10
+ @config = config
11
+ end
12
+
13
+ def call(env)
14
+ @request = Rack::Request.new(env)
15
+ Rack::Response.new do |response|
16
+ response.write(<<~HERE)
17
+ <html>
18
+ <head>
19
+ <link rel="openid2.provider" href="#{op_endpoint}" />
20
+ <link rel="openid.server" href="#{op_endpoint}" />
21
+ </head>
22
+ <body>
23
+ <h1>This is #{@config["identity"]} identity page</h1>
24
+ </body>
25
+ </html>
26
+ HERE
27
+ end.finish
28
+ end
29
+
30
+ def op_endpoint
31
+ "http://%s:%d/server/%s" % [
32
+ @request.host,
33
+ @request.port,
34
+ (@request.params["openid.success"] ? "?openid.success=true" : ""),
35
+ ]
36
+ end
37
+ end
@@ -0,0 +1,53 @@
1
+ require "rack/openid" # rack-openid2
2
+ require "rack/session"
3
+
4
+ module Rots
5
+ module Mocks
6
+ class ClientApp
7
+ extend Forwardable
8
+
9
+ attr_reader :app, :options
10
+
11
+ def_delegator :@app, :call
12
+
13
+ def initialize(**options)
14
+ @options = options.dup
15
+
16
+ @options[:identifier] ||= "#{Rots::Mocks::RotsServer::SERVER_URL}/john.doe?openid.success=true"
17
+
18
+ @app = Rack::Session::Pool.new(Rack::OpenID.new(rack_app))
19
+ end
20
+
21
+ private
22
+
23
+ def rack_app
24
+ # block passed to new is evaluated with instance_eval,
25
+ # which searches `binding` for local variables,
26
+ # while `self` is searched for instance variables and methods.
27
+ # A local pointer in `binding` to @options makes it accessible.
28
+ options = @options
29
+ lambda { |env|
30
+ if (resp = env[Rack::OpenID::RESPONSE])
31
+ headers = {
32
+ "X-Path" => env["PATH_INFO"],
33
+ "X-Method" => env["REQUEST_METHOD"],
34
+ "X-Query-String" => env["QUERY_STRING"],
35
+ }
36
+ if resp.status == :success
37
+ [200, headers, [resp.status.to_s]]
38
+ elsif resp.status == :setup_needed
39
+ headers["Location"] = Rots::Mocks::RotsServer::SERVER_URL # TODO update Rots to properly send user_setup_url. This should come from resp.
40
+ [307, headers, [resp.status.to_s]]
41
+ else
42
+ [400, headers, [resp.status.to_s]]
43
+ end
44
+ elsif env["MOCK_HTTP_BASIC_AUTH"]
45
+ [401, {Rack::OpenID::AUTHENTICATE_HEADER => 'Realm="Example"'}, []]
46
+ else
47
+ [401, {Rack::OpenID::AUTHENTICATE_HEADER => Rack::OpenID.build_header(options)}, []]
48
+ end
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,34 @@
1
+ require "openid" # ruby-openid2
2
+ require "rack/utils"
3
+ require "net/http" # stdlib in Ruby < 3, gem after
4
+ require "net/protocol"
5
+
6
+ module Rots
7
+ module Mocks
8
+ class Fetcher
9
+ def initialize(app)
10
+ @app = app
11
+ end
12
+
13
+ def fetch(url, body = nil, headers = nil, limit = nil)
14
+ opts = (headers || {}).dup
15
+ opts[:input] = body
16
+ opts[:method] = "POST" if body
17
+ env = Rack::MockRequest.env_for(url, opts)
18
+
19
+ status, headers, body = @app.call(env)
20
+
21
+ buf = []
22
+ buf << "HTTP/1.1 #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
23
+ headers.each { |header, value| buf << "#{header}: #{value}" }
24
+ buf << ""
25
+ body.each { |part| buf << part }
26
+
27
+ io = Net::BufferedIO.new(StringIO.new(buf.join("\n")))
28
+ res = Net::HTTPResponse.read_new(io)
29
+ res.reading_body(io, true) {}
30
+ OpenID::HTTPResponse._from_net_response(res, url)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ module Rots
2
+ module Mocks
3
+ class RotsServer
4
+ extend Forwardable
5
+ SERVER_URL = "http://localhost:9292"
6
+ DEFAULT_CONFIG = {
7
+ "identity" => "john.doe",
8
+ "sreg" => {
9
+ "nickname" => "jdoe",
10
+ "fullname" => "John Doe",
11
+ "email" => "jhon@doe.com",
12
+ "dob" => Date.parse("1985-09-21"),
13
+ "gender" => "M",
14
+ }.freeze,
15
+ }.freeze
16
+
17
+ attr_reader :app, :config
18
+
19
+ def_delegator :@app, :call
20
+
21
+ # @param config [Hash, nil] - the configuration of the app's authorizable identity
22
+ def initialize(config = nil)
23
+ @config ||= DEFAULT_CONFIG
24
+ raise ArgumentError, "config must be a Hash" unless self.config.is_a?(Hash)
25
+
26
+ @app = rack_app
27
+ end
28
+
29
+ private
30
+
31
+ def rack_app
32
+ # block passed to new is evaluated with instance_eval,
33
+ # which searches `binding` for local variables,
34
+ # while `self` is searched for instance variables and methods.
35
+ # A local pointer in `binding` to @config makes it accessible.
36
+ config = @config
37
+ Rack::Builder.new do
38
+ map("/%s" % config["identity"]) do
39
+ run(Rots::IdentityPageApp.new(config, {}))
40
+ end
41
+
42
+ map("/server") do
43
+ run(Rots::ServerApp.new(config, storage: Dir.tmpdir))
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
data/lib/rots/mocks.rb ADDED
@@ -0,0 +1,8 @@
1
+ # Not in the runtime dependencies.
2
+ # If you use the mocks, you need to add `rack-openid2` to your Gemfile.
3
+ require "rack/openid" # rack-openid2
4
+
5
+ # this gem's test support files:
6
+ require_relative "mocks/mock_fetcher"
7
+ require_relative "mocks/rots_server"
8
+ require_relative "mocks/client_app"