sinatra-portier 1.5.2 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbb567b7fdc34ac49a53113b97b08a27b52c2fd1e85552c2ea44eb7cabfc9666
4
- data.tar.gz: 3528e61f4a6fdc75ed3d2aee2bb80235a139860ca079b63d6ee3cfac487adbf3
3
+ metadata.gz: 31afe71da2eac370eaa964127e62202abf4917c535e7309d317e8e089476a834
4
+ data.tar.gz: b9bbcb6d954ba8e0653bf277d52df97333b25ac26ea5e5e64608b70067c2b97e
5
5
  SHA512:
6
- metadata.gz: ce0b199ca249d27d1cefc7db7c25f6bb5595165d7076843a190c448e61b596fcd2b0e3c362ddaf155ca6f7fb3002a73511b0ba4a8f111a5ffc1f5b1bc7b8e15c
7
- data.tar.gz: 5c6e1b3cc2890c87f32bda865530accd31ff97df69c5977d1c1de5009337cda8f38447756da9ca202cfae8d34859c8f9d98a6a606efc4d76120ec5587dedceba
6
+ metadata.gz: 30d0daa34b639d24fb2b0cc6dc71bf693bd6a702ddab6d811e8742116edd13e6470f3c2814c84b41dda9515cb0459224a9268b9bc920a84bfee42c1b5d5c0918
7
+ data.tar.gz: a90b89b5e2263fe61507ea7f055962218d5f24821ac7b1af96caa8e2f504cf0fddb19720bc0104584531670362d37ec07ce469e39aad733e988df1d21bf5c8fd
@@ -61,9 +61,14 @@ module Sinatra
61
61
  redirect_url ||= request.url
62
62
  session['redirect_url'] = redirect_url
63
63
 
64
- nonce = session[:nonce]
65
- unless nonce
66
- session[:nonce] = nonce = SecureRandom.base64
64
+ if session[:nonce]
65
+ nonce = session[:nonce]
66
+ # Try to limit how many nonces are stored by keeping the session nonce alive
67
+ Cachy.delete_key(nonce)
68
+ Cachy.cache(nonce, expires_in: 600) { true }
69
+ else
70
+ session[:nonce] = nonce = SecureRandom.base64
71
+ Cachy.cache(nonce, expires_in: 600) { true }
67
72
  end
68
73
 
69
74
  template = ERB.new(Templates::LOGIN_BUTTON)
@@ -10,11 +10,21 @@ require "sinatra/base"
10
10
  require 'sinatra/browserid/helpers'
11
11
  require 'sinatra/browserid/template'
12
12
  require 'addressable/uri'
13
+ require 'cachy'
14
+ require 'moneta'
15
+
13
16
 
14
17
  # This module provides an interface to verify a users email address
15
18
  # with browserid.org.
16
19
  module Sinatra
17
20
  module BrowserID
21
+
22
+ # Init an in-memory cache via the cachy gem. We use this
23
+ # instead of the session because of dropped sessions
24
+ # after redirects, see https://github.com/sinatra/sinatra/issues/1742.
25
+ Cachy.cache_store = Moneta.new(:Memory, expires: 600) # 10 minutes
26
+ # We need to set a global :expires here because of https://github.com/grosser/cachy/issues/7
27
+
18
28
  def self.registered(app)
19
29
  app.helpers BrowserID::Helpers
20
30
 
@@ -25,24 +35,27 @@ module Sinatra
25
35
  app.set :browserid_button_text, "Log in"
26
36
 
27
37
  app.get '/_browserid_login' do
28
- # TODO(petef): render a page that initiates login without
29
- # waiting for a user click.
30
38
  render_login_button
31
39
  end
32
40
 
33
41
  app.post '/_browserid_assert' do
34
42
  begin
35
- # 3. Server checks signature
36
- # for that, fetch the public key from the LA instance (TODO: Do that beforehand for trusted instances, and generally cache the key)
43
+ # Server checks signature
44
+ # For that, fetch the public key from the LA instance (TODO: Do that beforehand for trusted instances, and generally cache the key)
37
45
  public_key_jwks_uri = Addressable::URI.parse(settings.browserid_url + '/keys.json')
38
46
  public_key_jwks = ::JSON.parse(URI.parse(public_key_jwks_uri).read)
39
47
  public_key = OpenSSL::PKey::RSA.new
40
48
  if public_key.respond_to? :set_key
41
- # set n and d via the new set_key function, as direct access to n and e is blocked for some ruby and openssl versions.
42
- # Note that we have no d, as this is a public key, which would be the third param
43
- public_key.set_key( (OpenSSL::BN.new UrlSafeBase64.decode64(public_key_jwks["keys"][0]["n"]), 2),
44
- (OpenSSL::BN.new UrlSafeBase64.decode64(public_key_jwks["keys"][0]["e"]), 2),
45
- nil)
49
+ # We initially set n and d via the then new set_key function, as direct access to n and e is blocked for some ruby and openssl versions.
50
+ # But with OpenSSL 3 this function throws an error, as keys are immutable now. Instead we have to generate the key directly with
51
+ # the right params, as in https://github.com/railslove/epics/issues/138
52
+ sequence = []
53
+ # modulus:
54
+ sequence << OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(UrlSafeBase64.decode64(public_key_jwks["keys"][0]["n"]), 2))
55
+ # exponent:
56
+ sequence << OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(UrlSafeBase64.decode64(public_key_jwks["keys"][0]["e"]), 2))
57
+
58
+ public_key = OpenSSL::PKey::RSA.new(OpenSSL::ASN1::Sequence(sequence).to_der)
46
59
  else
47
60
  public_key.e = OpenSSL::BN.new UrlSafeBase64.decode64(public_key_jwks["keys"][0]["e"]), 2
48
61
  public_key.n = OpenSSL::BN.new UrlSafeBase64.decode64(public_key_jwks["keys"][0]["n"]), 2
@@ -50,19 +63,25 @@ module Sinatra
50
63
 
51
64
  id_token = JWT.decode params[:id_token], public_key, true, { :algorithm => 'RS256' }
52
65
  id_token = id_token[0]
53
- # 4. Needs to make sure token is still valid
66
+ # Needs to make sure token is still valid
54
67
  if (id_token["iss"] == settings.browserid_url &&
55
68
  id_token["aud"] == request.base_url.chomp('/') &&
56
69
  id_token["exp"] > Time.now.to_i &&
57
70
  id_token["email_verified"] &&
58
- id_token["nonce"] == session[:nonce])
71
+ # nonce is really known to us
72
+ Cachy.get(id_token["nonce"]))
59
73
  session[:browserid_email] = id_token['email']
60
- session.delete(:nonce)
74
+ Cachy.delete_key(id_token["nonce"])
75
+ session.delete(:nonce) # it's possible the session persisted
61
76
  if session['redirect_url']
62
77
  redirect session['redirect_url']
63
78
  else
64
79
  redirect "/"
65
80
  end
81
+ else
82
+ # Even when the token check failed the nonce has to be invalidated
83
+ Cachy.delete_key(id_token["nonce"])
84
+ session.delete(:nonce)
66
85
  end
67
86
  rescue OpenURI::HTTPError => e
68
87
  puts "could not validate token: " + e.to_s
@@ -70,8 +89,8 @@ module Sinatra
70
89
  halt 403
71
90
 
72
91
  end
73
- end # def self.registered
74
- end # module BrowserID
92
+ end
93
+ end
75
94
  register BrowserID
76
- end # module Sinatra
95
+ end
77
96
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-portier
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pete Fritchman
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-09-05 00:00:00.000000000 Z
12
+ date: 2023-11-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sinatra
@@ -81,6 +81,34 @@ dependencies:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '2.8'
84
+ - !ruby/object:Gem::Dependency
85
+ name: cachy
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0.4'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0.4'
98
+ - !ruby/object:Gem::Dependency
99
+ name: moneta
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '1.4'
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '1.4'
84
112
  description:
85
113
  email:
86
114
  - malte@paskuda.biz
@@ -114,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
142
  - !ruby/object:Gem::Version
115
143
  version: '0'
116
144
  requirements: []
117
- rubygems_version: 3.2.22
145
+ rubygems_version: 3.4.10
118
146
  signing_key:
119
147
  specification_version: 4
120
148
  summary: Sinatra extension for user authentication with portier