rots 1.0.0

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.
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"