omniauth-auth0 2.0.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of omniauth-auth0 might be problematic. Click here for more details.

data/README.md CHANGED
@@ -1,57 +1,70 @@
1
- [![Build Status](https://travis-ci.org/auth0/omniauth-auth0.svg)](https://travis-ci.org/auth0/omniauth-auth0)
2
-
3
1
  # OmniAuth Auth0
4
2
 
5
- This is the official [OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating to [Auth0](https://auth0.com).
3
+ An [OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating with [Auth0](https://auth0.com). This strategy is based on the [OmniAuth OAuth2](https://github.com/omniauth/omniauth-oauth2) strategy.
6
4
 
7
- ## Installing
5
+ > :warning: **Important security note:** This solution uses a 3rd party library with an unresolved [security issue(s)](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-9284). Please review the details of the vulnerability, including [Auth0](https://github.com/auth0/omniauth-auth0/issues/82 ) and other recommended [mitigations](https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284), before implementing the solution.
8
6
 
9
- Add to your `Gemfile`:
7
+ [![CircleCI](https://img.shields.io/circleci/project/github/auth0/omniauth-auth0/master.svg)](https://circleci.com/gh/auth0/omniauth-auth0)
8
+ [![codecov](https://codecov.io/gh/auth0/omniauth-auth0/branch/master/graph/badge.svg)](https://codecov.io/gh/auth0/omniauth-auth0)
9
+ [![Gem Version](https://badge.fury.io/rb/omniauth-auth0.svg)](https://badge.fury.io/rb/omniauth-auth0)
10
+ [![MIT licensed](https://img.shields.io/dub/l/vibe-d.svg?style=flat)](https://github.com/auth0/omniauth-auth0/blob/master/LICENSE)
11
+ [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fauth0%2Fomniauth-auth0.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fauth0%2Fomniauth-auth0?ref=badge_shield)
10
12
 
11
- ```ruby
12
- gem 'omniauth-auth0'
13
- ```
13
+ ## Table of Contents
14
14
 
15
- Then `bundle install`.
15
+ - [Documentation](#documentation)
16
+ - [Installation](#installation)
17
+ - [Getting Started](#getting-started)
18
+ - [Contribution](#contribution)
19
+ - [Support + Feedback](#support--feedback)
20
+ - [Vulnerability Reporting](#vulnerability-reporting)
21
+ - [What is Auth0](#what-is-auth0)
22
+ - [License](#license)
16
23
 
17
- ## Usage
24
+ ## Documentation
18
25
 
19
- ### Rails
26
+ - [Ruby on Rails Quickstart](https://auth0.com/docs/quickstart/webapp/rails)
27
+ - [Sample projects](https://github.com/auth0-samples/auth0-rubyonrails-sample)
20
28
 
21
- ```ruby
22
- Rails.application.config.middleware.use OmniAuth::Builder do
23
- provider :auth0, ENV['AUTH0_CLIENT_ID'], ENV['AUTH0_CLIENT_SECRET'], ENV['AUTH0_DOMAIN']
24
- end
25
- ```
29
+ ## Installation
26
30
 
27
- Then to redirect to your tenant's hosted login page:
31
+ Add the following line to your `Gemfile`:
28
32
 
29
33
  ```ruby
30
- redirect_to '/auth/auth0'
34
+ gem 'omniauth-auth0'
31
35
  ```
32
36
 
33
- ### Sinatra
37
+ If you're using this strategy with Rails, also add the following for CSRF protection:
34
38
 
35
39
  ```ruby
36
- use OmniAuth::Builder do
37
- provider :auth0, ENV['AUTH0_CLIENT_ID'], ENV['AUTH0_CLIENT_SECRET'], ENV['AUTH0_DOMAIN']
38
- end
40
+ gem 'omniauth-rails_csrf_protection'
39
41
  ```
40
42
 
41
- Then to redirect to your tenant's hosted login page:
43
+ Then install:
42
44
 
43
- ```ruby
44
- redirect to('/auth/auth0')
45
+ ```bash
46
+ $ bundle install
45
47
  ```
46
48
 
47
- > You can customize your hosted login page in your [Auth0 Dashboard](https://manage.auth0.com/#/login_page)
49
+ See our [contributing guide](CONTRIBUTING.md) for information on local installation for development.
50
+
51
+ ## Getting Started
52
+
53
+ To start processing authentication requests, the following steps must be performed:
48
54
 
49
- ### Auth parameters
55
+ 1. Initialize the strategy
56
+ 2. Configure the callback controller
57
+ 3. Add the required routes
58
+ 4. Trigger an authentication request
50
59
 
51
- To send additional parameters during login you can specify them when you register the provider
60
+ All of these tasks and more are covered in our [Ruby on Rails Quickstart](https://auth0.com/docs/quickstart/webapp/rails).
61
+
62
+ ### Additional authentication parameters
63
+
64
+ To send additional parameters during login, you can specify them when you register the provider:
52
65
 
53
66
  ```ruby
54
- provider
67
+ provider
55
68
  :auth0,
56
69
  ENV['AUTH0_CLIENT_ID'],
57
70
  ENV['AUTH0_CLIENT_SECRET'],
@@ -59,85 +72,101 @@ provider
59
72
  {
60
73
  authorize_params: {
61
74
  scope: 'openid read:users write:order',
62
- audience: 'https://mydomain/api'
75
+ audience: 'https://mydomain/api',
76
+ max_age: 3600 # time in seconds authentication is valid
63
77
  }
64
78
  }
65
79
  ```
66
80
 
67
- that will tell it to send those parameters on every Auth request.
81
+ ... which will tell the strategy to send those parameters on every authentication request.
82
+
83
+ ### Authentication hash
68
84
 
69
- Or you can do it for a specific Auth request by adding them in the query parameter of the redirect url:
85
+ The Auth0 strategy will provide the standard OmniAuth hash attributes:
86
+
87
+ - `:provider` - the name of the strategy, in this case `auth0`
88
+ - `:uid` - the user identifier
89
+ - `:info` - the result of the call to `/userinfo` using OmniAuth standard attributes
90
+ - `:credentials` - tokens requested and data
91
+ - `:extra` - Additional info obtained from calling `/userinfo` in the `:raw_info` property
70
92
 
71
93
  ```ruby
72
- redirect_to '/auth/auth0?connection=google-oauth2'
94
+ {
95
+ :provider => 'auth0',
96
+ :uid => 'auth0|USER_ID',
97
+ :info => {
98
+ :name => 'John Foo',
99
+ :email => 'johnfoo@example.org',
100
+ :nickname => 'john',
101
+ :image => 'https://example.org/john.jpg'
102
+ },
103
+ :credentials => {
104
+ :token => 'ACCESS_TOKEN',
105
+ :expires_at => 1485373937,
106
+ :expires => true,
107
+ :refresh_token => 'REFRESH_TOKEN',
108
+ :id_token => 'JWT_ID_TOKEN',
109
+ :token_type => 'bearer',
110
+ },
111
+ :extra => {
112
+ :raw_info => {
113
+ :email => 'johnfoo@example.org',
114
+ :email_verified => 'true',
115
+ :name => 'John Foo',
116
+ :picture => 'https://example.org/john.jpg',
117
+ :user_id => 'auth0|USER_ID',
118
+ :nickname => 'john',
119
+ :created_at => '2014-07-15T17:19:50.387Z'
120
+ }
121
+ }
122
+ }
73
123
  ```
74
124
 
75
- ### Auth Hash
125
+ ### Query Parameter Options
76
126
 
77
- Auth0 strategy will have the standard OmniAuth hash attributes:
127
+ In some scenarios, you may need to pass specific query parameters to `/authorize`. The following parameters are available to enable this:
78
128
 
79
- - provider: the name of the strategy, in this case `auth0`
80
- - uid: the user identifier
81
- - info: the result of the call to /userinfo using OmniAuth standard attributes
82
- - credentials: Auth0 tokens, at least will have an access_token but can eventually have refresh_token and/or id_token
83
- - extra: Additional info obtained from calling /userinfo in the attribute `raw_info`
129
+ - `connection`
130
+ - `connection_scope`
131
+ - `prompt`
132
+ - `screen_hint` (only relevant to New Universal Login Experience)
84
133
 
85
- ```ruby
86
- {
87
- :provider => 'auth0',
88
- :uid => 'google-oauth2|this-is-the-google-id',
89
- :info => {
90
- :name => 'John Foo',
91
- :email => 'johnfoo@example.org',
92
- :nickname => 'john',
93
- :image => 'https://example.org/john.jpg'
94
- },
95
- :credentials => {
96
- :token => 'XdDadllcas2134rdfdsI',
97
- :expires_at => 1485373937,
98
- :expires => true,
99
- :refresh_token => 'aKNajdjfj123nBasd',
100
- :id_token => 'eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBGb28ifQ.lxAiy1rqve8ZHQEQVehUlP1sommPHVJDhgPgFPnDosg',
101
- :token_type => 'bearer',
102
- },
103
- :extra => {
104
- :raw_info => {
105
- :email => 'johnfoo@example.org',
106
- :email_verified => 'true',
107
- :name => 'John Foo',
108
- :picture => 'https://example.org/john.jpg',
109
- :user_id => 'google-oauth2|this-is-the-google-id',
110
- :nickname => 'john',
111
- :created_at: '2014-07-15T17:19:50.387Z'
112
- }
113
- }
114
- }
115
- ```
134
+ Simply pass these query parameters to your OmniAuth redirect endpoint to enable their behavior.
116
135
 
117
- ### ActionDispatch::Cookies::CookieOverflow issue
136
+ ## Contribution
118
137
 
119
- If you are getting this error it means that you are using Cookie sessions and since you are storing the whole profile it overflows the max-size of 4K.
138
+ We appreciate feedback and contribution to this repo! Before you get started, please see the following:
120
139
 
121
- You can change to use In-Memory store for development as follows:
140
+ - [Auth0's contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md)
141
+ - [Auth0's Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md)
142
+ - [This repo's contribution guide](CONTRIBUTING.md)
122
143
 
123
- # /config/initializers/session_store.rb
124
- CrazyApp::Application.config.session_store :cache_store
144
+ ## Support + Feedback
125
145
 
126
- # /config/environments/development.rb
127
- config.cache_store = :memory_store
146
+ - Use [Community](https://community.auth0.com/) for usage, questions, specific cases.
147
+ - Use [Issues](https://github.com/auth0/omniauth-auth0/issues) here for code-level support and bug reports.
148
+ - Paid customers can use [Support](https://support.auth0.com/) to submit a trouble ticket for production-affecting issues.
128
149
 
129
- ## Documentation
150
+ ## Vulnerability Reporting
130
151
 
131
- For more information about [auth0](http://auth0.com) contact our [documentation page](http://docs.auth0.com/).
152
+ Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.
132
153
 
133
- ## Issue Reporting
154
+ ## What is Auth0?
134
155
 
135
- If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.
156
+ Auth0 helps you to easily:
136
157
 
137
- ## Author
158
+ - implement authentication with multiple identity providers, including social (e.g., Google, Facebook, Microsoft, LinkedIn, GitHub, Twitter, etc), or enterprise (e.g., Windows Azure AD, Google Apps, Active Directory, ADFS, SAML, etc.)
159
+ - log in users with username/password databases, passwordless, or multi-factor authentication
160
+ - link multiple user accounts together
161
+ - generate signed JSON Web Tokens to authorize your API calls and flow the user identity securely
162
+ - access demographics and analytics detailing how, when, and where users are logging in
163
+ - enrich user profiles from other data sources using customizable JavaScript rules
138
164
 
139
- [Auth0](https://auth0.com)
165
+ [Why Auth0?](https://auth0.com/why-auth0)
140
166
 
141
167
  ## License
142
168
 
143
- This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.
169
+ The OmniAuth Auth0 strategy is licensed under MIT - [LICENSE](LICENSE)
170
+
171
+
172
+ [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fauth0%2Fomniauth-auth0.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fauth0%2Fomniauth-auth0?ref=badge_large)
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ begin
10
10
  RuboCop::RakeTask.new
11
11
  rescue LoadError
12
12
  task :rubocop do
13
- $stderr.puts 'Rubocop is disabled'
13
+ warn 'Rubocop is disabled'
14
14
  end
15
15
  end
16
16
 
@@ -23,7 +23,7 @@ namespace :sinatra do
23
23
  end
24
24
 
25
25
  desc 'Run specs'
26
- task default: [:spec, :rubocop]
26
+ task default: %i[spec rubocop]
27
27
  task test: :spec
28
28
  task :guard do
29
29
  system 'bundle exec guard'
@@ -0,0 +1,22 @@
1
+ coverage:
2
+ precision: 2
3
+ round: down
4
+ range: "60...100"
5
+ status:
6
+ project:
7
+ default:
8
+ enabled: true
9
+ target: auto
10
+ threshold: 5%
11
+ if_no_uploads: error
12
+ patch:
13
+ default:
14
+ enabled: true
15
+ target: 80%
16
+ threshold: 30%
17
+ if_no_uploads: error
18
+ changes:
19
+ default:
20
+ enabled: true
21
+ if_no_uploads: error
22
+ comment: false
@@ -1,2 +1,2 @@
1
- require 'omniauth-auth0/version' # rubocop:disable Style/FileName
1
+ require 'omniauth-auth0/version'
2
2
  require 'omniauth/strategies/auth0'
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module Auth0
3
- VERSION = '2.0.0'.freeze
3
+ VERSION = '2.4.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,11 @@
1
+ module OmniAuth
2
+ module Auth0
3
+ class TokenValidationError < StandardError
4
+ attr_reader :error_reason
5
+ def initialize(msg)
6
+ @error_reason = msg
7
+ super(msg)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,228 @@
1
+ require 'base64'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'omniauth'
5
+ require 'omniauth/auth0/errors'
6
+
7
+ module OmniAuth
8
+ module Auth0
9
+ # JWT Validator class
10
+ class JWTValidator
11
+ attr_accessor :issuer, :domain
12
+
13
+ # Initializer
14
+ # @param options object
15
+ # options.domain - Application domain.
16
+ # options.issuer - Application issuer (optional).
17
+ # options.client_id - Application Client ID.
18
+ # options.client_secret - Application Client Secret.
19
+
20
+ def initialize(options, authorize_params = {})
21
+ @domain = uri_string(options.domain)
22
+
23
+ # Use custom issuer if provided, otherwise use domain
24
+ @issuer = @domain
25
+ @issuer = uri_string(options.issuer) if options.respond_to?(:issuer)
26
+
27
+ @client_id = options.client_id
28
+ @client_secret = options.client_secret
29
+ end
30
+
31
+ def verify_signature(jwt)
32
+ head = token_head(jwt)
33
+
34
+ # Make sure the algorithm is supported and get the decode key.
35
+ if head[:alg] == 'RS256'
36
+ [rs256_decode_key(head[:kid]), head[:alg]]
37
+ elsif head[:alg] == 'HS256'
38
+ [@client_secret, head[:alg]]
39
+ else
40
+ raise OmniAuth::Auth0::TokenValidationError.new("Signature algorithm of #{head[:alg]} is not supported. Expected the ID token to be signed with RS256 or HS256")
41
+ end
42
+ end
43
+
44
+ # Verify a JWT.
45
+ # @param jwt string - JWT to verify.
46
+ # @param authorize_params hash - Authorization params to verify on the JWT
47
+ # @return hash - The verified token, if there were no exceptions.
48
+ def verify(jwt, authorize_params = {})
49
+ if !jwt
50
+ raise OmniAuth::Auth0::TokenValidationError.new('ID token is required but missing')
51
+ end
52
+
53
+ parts = jwt.split('.')
54
+ if parts.length != 3
55
+ raise OmniAuth::Auth0::TokenValidationError.new('ID token could not be decoded')
56
+ end
57
+
58
+ key, alg = verify_signature(jwt)
59
+ id_token, header = JWT.decode(jwt, key, false)
60
+ verify_claims(id_token, authorize_params)
61
+
62
+ return id_token
63
+ end
64
+
65
+ # Get the decoded head segment from a JWT.
66
+ # @return hash - The parsed head of the JWT passed, empty hash if not.
67
+ def token_head(jwt)
68
+ jwt_parts = jwt.split('.')
69
+ return {} if blank?(jwt_parts) || blank?(jwt_parts[0])
70
+
71
+ json_parse(Base64.decode64(jwt_parts[0]))
72
+ end
73
+
74
+ # Get the JWKS from the issuer and return a public key.
75
+ # @param x5c string - X.509 certificate chain from a JWKS.
76
+ # @return key - The X.509 certificate public key.
77
+ def jwks_public_cert(x5c)
78
+ x5c = Base64.decode64(x5c)
79
+
80
+ # https://docs.ruby-lang.org/en/2.4.0/OpenSSL/X509/Certificate.html
81
+ OpenSSL::X509::Certificate.new(x5c).public_key
82
+ end
83
+
84
+ # Return a specific key from a JWKS object.
85
+ # @param key string - Key to find in the JWKS.
86
+ # @param kid string - Key ID to identify the right JWK.
87
+ # @return nil|string
88
+ def jwks_key(key, kid)
89
+ return nil if blank?(jwks[:keys])
90
+
91
+ matching_jwk = jwks[:keys].find { |jwk| jwk[:kid] == kid }
92
+ matching_jwk[key] if matching_jwk
93
+ end
94
+
95
+ private
96
+ def rs256_decode_key(kid)
97
+ jwks_x5c = jwks_key(:x5c, kid)
98
+
99
+ if jwks_x5c.nil?
100
+ raise OmniAuth::Auth0::TokenValidationError.new("Could not find a public key for Key ID (kid) '#{kid}''")
101
+ end
102
+
103
+ jwks_public_cert(jwks_x5c.first)
104
+ end
105
+
106
+ # Get a JWKS from the domain
107
+ # @return void
108
+ def jwks
109
+ jwks_uri = URI(@domain + '.well-known/jwks.json')
110
+ @jwks ||= json_parse(Net::HTTP.get(jwks_uri))
111
+ end
112
+
113
+ # Rails Active Support blank method.
114
+ # @param obj object - Object to check for blankness.
115
+ # @return boolean
116
+ def blank?(obj)
117
+ obj.respond_to?(:empty?) ? obj.empty? : !obj
118
+ end
119
+
120
+ # Parse JSON with symbolized names.
121
+ # @param json string - JSON to parse.
122
+ # @return hash
123
+ def json_parse(json)
124
+ JSON.parse(json, symbolize_names: true)
125
+ end
126
+
127
+ # Parse a URI into the desired string format
128
+ # @param uri - the URI to parse
129
+ # @return string
130
+ def uri_string(uri)
131
+ temp_domain = URI(uri)
132
+ temp_domain = URI("https://#{uri}") unless temp_domain.scheme
133
+ "#{temp_domain}/"
134
+ end
135
+
136
+ def verify_claims(id_token, authorize_params)
137
+ leeway = authorize_params[:leeway] || 60
138
+ max_age = authorize_params[:max_age]
139
+ nonce = authorize_params[:nonce]
140
+
141
+ verify_iss(id_token)
142
+ verify_sub(id_token)
143
+ verify_aud(id_token)
144
+ verify_expiration(id_token, leeway)
145
+ verify_iat(id_token)
146
+ verify_nonce(id_token, nonce)
147
+ verify_azp(id_token)
148
+ verify_auth_time(id_token, leeway, max_age)
149
+ end
150
+
151
+ def verify_iss(id_token)
152
+ issuer = id_token['iss']
153
+ if !issuer
154
+ raise OmniAuth::Auth0::TokenValidationError.new("Issuer (iss) claim must be a string present in the ID token")
155
+ elsif @issuer != issuer
156
+ raise OmniAuth::Auth0::TokenValidationError.new("Issuer (iss) claim mismatch in the ID token, expected (#{@issuer}), found (#{id_token['iss']})")
157
+ end
158
+ end
159
+
160
+ def verify_sub(id_token)
161
+ subject = id_token['sub']
162
+ if !subject || !subject.is_a?(String) || subject.empty?
163
+ raise OmniAuth::Auth0::TokenValidationError.new('Subject (sub) claim must be a string present in the ID token')
164
+ end
165
+ end
166
+
167
+ def verify_aud(id_token)
168
+ audience = id_token['aud']
169
+ if !audience || !(audience.is_a?(String) || audience.is_a?(Array))
170
+ raise OmniAuth::Auth0::TokenValidationError.new("Audience (aud) claim must be a string or array of strings present in the ID token")
171
+ elsif audience.is_a?(Array) && !audience.include?(@client_id)
172
+ raise OmniAuth::Auth0::TokenValidationError.new("Audience (aud) claim mismatch in the ID token; expected #{@client_id} but was not one of #{audience.join(', ')}")
173
+ elsif audience.is_a?(String) && audience != @client_id
174
+ raise OmniAuth::Auth0::TokenValidationError.new("Audience (aud) claim mismatch in the ID token; expected #{@client_id} but found #{audience}")
175
+ end
176
+ end
177
+
178
+ def verify_expiration(id_token, leeway)
179
+ expiration = id_token['exp']
180
+ if !expiration || !expiration.is_a?(Integer)
181
+ raise OmniAuth::Auth0::TokenValidationError.new("Expiration time (exp) claim must be a number present in the ID token")
182
+ elsif expiration <= Time.now.to_i - leeway
183
+ raise OmniAuth::Auth0::TokenValidationError.new("Expiration time (exp) claim error in the ID token; current time (#{Time.now}) is after expiration time (#{Time.at(expiration + leeway)})")
184
+ end
185
+ end
186
+
187
+ def verify_iat(id_token)
188
+ if !id_token['iat']
189
+ raise OmniAuth::Auth0::TokenValidationError.new("Issued At (iat) claim must be a number present in the ID token")
190
+ end
191
+ end
192
+
193
+ def verify_nonce(id_token, nonce)
194
+ if nonce
195
+ received_nonce = id_token['nonce']
196
+ if !received_nonce
197
+ raise OmniAuth::Auth0::TokenValidationError.new("Nonce (nonce) claim must be a string present in the ID token")
198
+ elsif nonce != received_nonce
199
+ raise OmniAuth::Auth0::TokenValidationError.new("Nonce (nonce) claim value mismatch in the ID token; expected (#{nonce}), found (#{received_nonce})")
200
+ end
201
+ end
202
+ end
203
+
204
+ def verify_azp(id_token)
205
+ audience = id_token['aud']
206
+ if audience.is_a?(Array) && audience.length > 1
207
+ azp = id_token['azp']
208
+ if !azp || !azp.is_a?(String)
209
+ raise OmniAuth::Auth0::TokenValidationError.new("Authorized Party (azp) claim must be a string present in the ID token when Audience (aud) claim has multiple values")
210
+ elsif azp != @client_id
211
+ raise OmniAuth::Auth0::TokenValidationError.new("Authorized Party (azp) claim mismatch in the ID token; expected (#{@client_id}), found (#{azp})")
212
+ end
213
+ end
214
+ end
215
+
216
+ def verify_auth_time(id_token, leeway, max_age)
217
+ if max_age
218
+ auth_time = id_token['auth_time']
219
+ if !auth_time || !auth_time.is_a?(Integer)
220
+ raise OmniAuth::Auth0::TokenValidationError.new("Authentication Time (auth_time) claim must be a number present in the ID token when Max Age (max_age) is specified")
221
+ elsif Time.now.to_i > auth_time + max_age + leeway;
222
+ raise OmniAuth::Auth0::TokenValidationError.new("Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (#{Time.now}) is after last auth time (#{Time.at(auth_time + max_age + leeway)})")
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
228
+ end