test_openid_connect 0.1.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: aa29bfd7d42d5bb0c60128294eadc6ca4a01ef84a6c01429b2d65dcc5a08dcb2
4
+ data.tar.gz: 455c3a250b7ac06dcaef9264b65f56bd1c5aa3e31a564594313ace407237539b
5
+ SHA512:
6
+ metadata.gz: 31b4cbb02487fe7c25a6426ab7355376a0780f7aab5c3c94cc794a22bee84e0710085ac1a1c60771163fdc76a24b63f14b700315b6a35492295185dea803b3e6
7
+ data.tar.gz: 4e0fded96c8e064ee6a26a0ea72fbbc5a9f292f60c5b11716bc6a56e6e56db2dcd0e72d93dfd48386df290e45fe0790fd5e45e85f1db58e5f0fd9c998c7beacf
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in test_openid_connect.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # TestOpenidConnect
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/test_openid_connect`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'test_openid_connect'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install test_openid_connect
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/test_openid_connect.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "test_openid_connect"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TestOpenidConnect
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth/openid_connect/version'
4
+ require 'omniauth/strategies/openid_connect
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth-oauth2'
4
+
5
+ module OmniAuth
6
+ module OpenIDConnect
7
+ class DiscoveryError < Error; end
8
+ end
9
+
10
+ module Strategies
11
+ class OpenIDConnect < OmniAuth::Strategies::OAuth2
12
+ option :scope, "openid"
13
+ option :discovery, true
14
+ option :use_userinfo, true
15
+ option :cache, lambda { |key, &blk| blk.call } # Default no-op cache
16
+ option :error_handler, lambda { |error, message| nil } # Default no-op handler
17
+ option :verbose_logger, lambda { |message| nil } # Default no-op handler
18
+ option :passthrough_authorize_options, [:p]
19
+ option :passthrough_token_options, [:p]
20
+
21
+ option :client_options,
22
+ discovery_document: nil,
23
+ site: nil,
24
+ authorize_url: nil,
25
+ token_url: nil,
26
+ userinfo_endpoint: nil,
27
+ auth_scheme: :basic_auth
28
+
29
+ def verbose_log(message)
30
+ options.verbose_logger.call(message)
31
+ end
32
+
33
+ def discover!
34
+ verbose_log("Fetching discovery document from #{options[:client_options][:discovery_document]}")
35
+ discovery_document = options.cache.call("openid_discovery_#{options[:client_options][:discovery_document]}") do
36
+ client.request(:get, options[:client_options][:discovery_document], parse: :json).parsed
37
+ end
38
+ verbose_log("Discovery document loaded\n\n#{discovery_document.to_yaml}")
39
+
40
+ discovery_params = {
41
+ authorize_url: "authorization_endpoint",
42
+ token_url: "token_endpoint",
43
+ site: "issuer"
44
+ }
45
+
46
+ discovery_params.each do |internal_key, external_key|
47
+ val = discovery_document[external_key].to_s
48
+ raise ::OmniAuth::OpenIDConnect::DiscoveryError.new("missing discovery parameter #{external_key}") if val.nil? || val.empty?
49
+ options[:client_options][internal_key] = val
50
+ end
51
+
52
+ userinfo_endpoint = options[:client_options][:userinfo_endpoint] = discovery_document["userinfo_endpoint"].to_s
53
+ options.use_userinfo = false if userinfo_endpoint.nil? || userinfo_endpoint.empty?
54
+ end
55
+
56
+ def request_phase
57
+ begin
58
+ discover! if options[:discovery]
59
+ rescue ::OmniAuth::OpenIDConnect::DiscoveryError => e
60
+ fail!(:openid_connect_discovery_error, e)
61
+ end
62
+
63
+ super
64
+ end
65
+
66
+ def authorize_params
67
+ super.tap do |params|
68
+ options[:passthrough_authorize_options].each do |k|
69
+ params[k] = request.params[k.to_s] unless [nil, ''].include?(request.params[k.to_s])
70
+ end
71
+
72
+ params[:scope] = options[:scope]
73
+ session['omniauth.nonce'] = params[:nonce] = SecureRandom.hex(32)
74
+
75
+ options[:passthrough_token_options].each do |k|
76
+ session["omniauth.param.#{k}"] = request.params[k.to_s] unless [nil, ''].include?(request.params[k.to_s])
77
+ end
78
+ end
79
+ end
80
+
81
+ def token_params
82
+ params = {}
83
+ options[:passthrough_token_options].each do |k|
84
+ val = session.delete("omniauth.param.#{k}")
85
+ params[k] = val unless [nil, ''].include?(val)
86
+ end
87
+ super.merge(params)
88
+ end
89
+
90
+ def callback_phase
91
+ if request.params["error"] && request.params["error_description"] && response = options.error_handler.call(request.params["error"], request.params["error_description"])
92
+ verbose_log("Error handled, redirecting\n\n#{response.to_yaml}")
93
+ return redirect(response)
94
+ end
95
+
96
+ begin
97
+ discover! if options[:discovery]
98
+
99
+ oauth2_callback_phase = super
100
+ return oauth2_callback_phase if env['omniauth.error']
101
+
102
+ if id_token_info["nonce"].nil? || id_token_info["nonce"].empty? || id_token_info["nonce"] != session.delete("omniauth.nonce")
103
+ return fail!(:csrf_detected, CallbackError.new(:csrf_detected, "CSRF detected"))
104
+ end
105
+ oauth2_callback_phase
106
+ rescue ::OmniAuth::OpenIDConnect::DiscoveryError => e
107
+ fail!(:openid_connect_discovery_error, e)
108
+ rescue JWT::DecodeError => e
109
+ fail!(:jwt_decode_failed, e)
110
+ end
111
+ end
112
+
113
+ def id_token_info
114
+ # Verify the claims in the JWT
115
+ # The signature does not need to be verified because the
116
+ # token was acquired via a direct server-server connection to the issuer
117
+ @id_token_info ||= begin
118
+ decoded = JWT.decode(access_token['id_token'], nil, false).first
119
+ verbose_log("Loaded JWT\n\n#{decoded.to_yaml}")
120
+ JWT::Verify.verify_claims(decoded,
121
+ verify_iss: true,
122
+ iss: options[:client_options][:site],
123
+ verify_aud: true,
124
+ aud: options.client_id,
125
+ verify_sub: false,
126
+ verify_expiration: true,
127
+ verify_not_before: true,
128
+ verify_iat: false,
129
+ verify_jti: false
130
+ )
131
+ verbose_log("Verified JWT\n\n#{decoded.to_yaml}")
132
+
133
+ decoded
134
+ end
135
+ end
136
+
137
+ def userinfo_response
138
+ @raw_info ||= begin
139
+ info = access_token.get(options[:client_options][:userinfo_endpoint]).parsed
140
+ verbose_log("Fetched userinfo response\n\n#{info.to_yaml}")
141
+ info
142
+ end
143
+
144
+ return fail!(:csrf_detected, CallbackError.new(:csrf_detected, "CSRF detected")) unless @raw_info['sub'] == id_token_info['sub']
145
+ @raw_info
146
+ end
147
+
148
+ uid { id_token_info['sub'] }
149
+
150
+ info do
151
+ data_source = options.use_userinfo ? userinfo_response : id_token_info
152
+ prune!(
153
+ name: data_source['nickname'],
154
+ email: data_source['email'],
155
+ first_name: data_source['given_name'],
156
+ last_name: data_source['family_name'],
157
+ nickname: data_source['nickname'],
158
+ image: data_source['picture']
159
+ )
160
+ end
161
+
162
+ extra do
163
+ hash = {}
164
+ hash[:raw_info] = options.use_userinfo ? userinfo_response : id_token_info
165
+ prune! hash
166
+ end
167
+
168
+ private
169
+
170
+ def callback_url
171
+ full_host + script_name + callback_path
172
+ end
173
+
174
+ def get_token_options
175
+ { redirect_uri: callback_url,
176
+ grant_type: 'authorization_code',
177
+ code: request.params["code"],
178
+ client_id: options[:client_id],
179
+ client_secret: options[:client_secret]
180
+ }.merge(token_params.to_hash(symbolize_keys: true))
181
+ end
182
+
183
+ def prune!(hash)
184
+ hash.delete_if do |_, v|
185
+ prune!(v) if v.is_a?(Hash)
186
+ v.nil? || (v.respond_to?(:empty?) && v.empty?)
187
+ end
188
+ end
189
+
190
+ protected
191
+
192
+ def build_access_token
193
+ return super if options.use_userinfo
194
+ response = client.request(:post, options[:client_options][:token_url], body: get_token_options)
195
+ ::OAuth2::AccessToken.from_hash(client, response.parsed)
196
+ end
197
+
198
+ end
199
+ end
200
+ end
201
+
202
+ OmniAuth.config.add_camelization 'openid_connect', 'OpenIDConnect'
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth/openid_connect'
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "test_openid_connect"
5
+ spec.version = "0.1.0"
6
+ spec.required_ruby_version = ">= 2.4.0"
7
+ spec.authors = ["Burak Akça"]
8
+ spec.email = ["burak.akca834@gmail.com"]
9
+
10
+ spec.summary = "summary summary"
11
+ spec.description = "desc desc desc desc "
12
+ spec.homepage = "https://github.com/burakakca/test-openid-connect"
13
+ spec.license = "MIT"
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ # Uncomment to register a new dependency of your gem
25
+ # spec.add_dependency "example-gem", "~> 1.0"
26
+
27
+ # For more information and examples about making a new gem, checkout our
28
+ # guide at: https://bundler.io/guides/creating_gem.html
29
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: test_openid_connect
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Burak Akça
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-08-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: 'desc desc desc desc '
14
+ email:
15
+ - burak.akca834@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - Gemfile
22
+ - README.md
23
+ - Rakefile
24
+ - bin/console
25
+ - bin/setup
26
+ - lib/omniauth/openid_connect.rb
27
+ - lib/omniauth/openid_connect/version.rb
28
+ - lib/omniauth/strategies/openid_connect.rb
29
+ - lib/test_openid_connect.rb
30
+ - test_openid_connect.gemspec
31
+ homepage: https://github.com/burakakca/test-openid-connect
32
+ licenses:
33
+ - MIT
34
+ metadata: {}
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 2.4.0
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubygems_version: 3.1.4
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: summary summary
54
+ test_files: []