omniauth-azure-activedirectory 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rubocop.yml +8 -0
- data/.rubocop_todo.yml +20 -0
- data/.travis.yml +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +98 -0
- data/Rakefile +22 -0
- data/examples/rails-todo-list-app/.gitignore +25 -0
- data/examples/rails-todo-list-app/Gemfile +33 -0
- data/examples/rails-todo-list-app/README.md +83 -0
- data/examples/rails-todo-list-app/Rakefile +3 -0
- data/examples/rails-todo-list-app/app/assets/javascripts/application.js +4 -0
- data/examples/rails-todo-list-app/app/assets/stylesheets/application.css +2 -0
- data/examples/rails-todo-list-app/app/controllers/application_controller.rb +3 -0
- data/examples/rails-todo-list-app/app/controllers/home_controller.rb +2 -0
- data/examples/rails-todo-list-app/app/controllers/profile_controller.rb +20 -0
- data/examples/rails-todo-list-app/app/controllers/sessions_controller.rb +28 -0
- data/examples/rails-todo-list-app/app/controllers/signed_in_controller.rb +25 -0
- data/examples/rails-todo-list-app/app/controllers/tasks_controller.rb +33 -0
- data/examples/rails-todo-list-app/app/models/task.rb +10 -0
- data/examples/rails-todo-list-app/app/models/user.rb +58 -0
- data/examples/rails-todo-list-app/app/views/home/index.html.haml +4 -0
- data/examples/rails-todo-list-app/app/views/layouts/application.html.haml +12 -0
- data/examples/rails-todo-list-app/app/views/layouts/signed_in.html.haml +18 -0
- data/examples/rails-todo-list-app/app/views/profile/index.html.haml +13 -0
- data/examples/rails-todo-list-app/app/views/tasks/index.html.haml +11 -0
- data/examples/rails-todo-list-app/bin/bundle +3 -0
- data/examples/rails-todo-list-app/bin/rails +4 -0
- data/examples/rails-todo-list-app/bin/rake +4 -0
- data/examples/rails-todo-list-app/bin/setup +29 -0
- data/examples/rails-todo-list-app/config.ru +4 -0
- data/examples/rails-todo-list-app/config/application.rb +29 -0
- data/examples/rails-todo-list-app/config/boot.rb +3 -0
- data/examples/rails-todo-list-app/config/database.yml +25 -0
- data/examples/rails-todo-list-app/config/environment.rb +13 -0
- data/examples/rails-todo-list-app/config/environments/development.rb +41 -0
- data/examples/rails-todo-list-app/config/environments/production.rb +79 -0
- data/examples/rails-todo-list-app/config/environments/test.rb +42 -0
- data/examples/rails-todo-list-app/config/initializers/assets.rb +11 -0
- data/examples/rails-todo-list-app/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails-todo-list-app/config/initializers/cookies_serializer.rb +3 -0
- data/examples/rails-todo-list-app/config/initializers/filter_parameter_logging.rb +4 -0
- data/examples/rails-todo-list-app/config/initializers/inflections.rb +16 -0
- data/examples/rails-todo-list-app/config/initializers/mime_types.rb +4 -0
- data/examples/rails-todo-list-app/config/initializers/omniauth.rb +3 -0
- data/examples/rails-todo-list-app/config/initializers/session_store.rb +3 -0
- data/examples/rails-todo-list-app/config/initializers/wrap_parameters.rb +14 -0
- data/examples/rails-todo-list-app/config/routes.rb +22 -0
- data/examples/rails-todo-list-app/db/schema.rb +35 -0
- data/examples/rails-todo-list-app/public/404.html +67 -0
- data/examples/rails-todo-list-app/public/422.html +67 -0
- data/examples/rails-todo-list-app/public/500.html +66 -0
- data/examples/rails-todo-list-app/public/favicon.ico +0 -0
- data/examples/sinatra-multiple-providers-app/.env +11 -0
- data/examples/sinatra-multiple-providers-app/Gemfile +8 -0
- data/examples/sinatra-multiple-providers-app/README.md +13 -0
- data/examples/sinatra-multiple-providers-app/app.rb +51 -0
- data/examples/sinatra-multiple-providers-app/config.ru +45 -0
- data/lib/omniauth-azure-activedirectory.rb +23 -0
- data/lib/omniauth/azure_activedirectory.rb +24 -0
- data/lib/omniauth/azure_activedirectory/version.rb +28 -0
- data/lib/omniauth/strategies/azure_activedirectory.rb +329 -0
- data/omniauth-azure-activedirectory.gemspec +25 -0
- data/spec/fixtures/id_token.txt +1 -0
- data/spec/fixtures/id_token_bad_audience.txt +1 -0
- data/spec/fixtures/id_token_bad_chash.txt +1 -0
- data/spec/fixtures/id_token_bad_issuer.txt +1 -0
- data/spec/fixtures/id_token_bad_kid.txt +1 -0
- data/spec/fixtures/id_token_bad_nonce.txt +1 -0
- data/spec/fixtures/id_token_no_alg.txt +1 -0
- data/spec/fixtures/x5c.txt +1 -0
- data/spec/fixtures/x5c_different.txt +1 -0
- data/spec/omniauth/strategies/azure_activedirectory_spec.rb +222 -0
- data/spec/spec_helper.rb +44 -0
- metadata +217 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2015 Micorosft Corporation
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#-------------------------------------------------------------------------------
|
22
|
+
|
23
|
+
require 'omniauth/azure_activedirectory'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2015 Micorosft Corporation
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#-------------------------------------------------------------------------------
|
22
|
+
|
23
|
+
require 'omniauth/azure_activedirectory/version'
|
24
|
+
require 'omniauth/strategies/azure_activedirectory'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2015 Micorosft Corporation
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#-------------------------------------------------------------------------------
|
22
|
+
|
23
|
+
module OmniAuth
|
24
|
+
# The release version.
|
25
|
+
module AzureActiveDirectory
|
26
|
+
VERSION = '1.0.0'
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,329 @@
|
|
1
|
+
#-------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2015 Micorosft Corporation
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#-------------------------------------------------------------------------------
|
22
|
+
|
23
|
+
require 'jwt'
|
24
|
+
require 'omniauth'
|
25
|
+
require 'openssl'
|
26
|
+
require 'securerandom'
|
27
|
+
|
28
|
+
module OmniAuth
|
29
|
+
module Strategies
|
30
|
+
# A strategy for authentication against Azure Active Directory.
|
31
|
+
class AzureActiveDirectory
|
32
|
+
include OmniAuth::AzureActiveDirectory
|
33
|
+
include OmniAuth::Strategy
|
34
|
+
|
35
|
+
class OAuthError < StandardError; end
|
36
|
+
|
37
|
+
##
|
38
|
+
# The client id (key) and tenant must be configured when the OmniAuth
|
39
|
+
# middleware is installed. Example:
|
40
|
+
#
|
41
|
+
# require 'omniauth'
|
42
|
+
# require 'omniauth-azure-activedirectory'
|
43
|
+
#
|
44
|
+
# use OmniAuth::Builder do
|
45
|
+
# provider :azure_activedirectory, ENV['AAD_KEY'], ENV['AAD_TENANT']
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
args [:client_id, :tenant]
|
49
|
+
option :client_id, nil
|
50
|
+
option :tenant, nil
|
51
|
+
|
52
|
+
# Field renaming is an attempt to fit the OmniAuth recommended schema as
|
53
|
+
# best as possible.
|
54
|
+
#
|
55
|
+
# @see https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema
|
56
|
+
uid { @claims['sub'] }
|
57
|
+
info do
|
58
|
+
{ name: @claims['name'],
|
59
|
+
email: @claims['email'] || @claims['upn'],
|
60
|
+
first_name: @claims['given_name'],
|
61
|
+
last_name: @claims['family_name'] }
|
62
|
+
end
|
63
|
+
credentials { { code: @code } }
|
64
|
+
extra do
|
65
|
+
{ session_state: @session_state,
|
66
|
+
raw_info:
|
67
|
+
{ id_token: @id_token,
|
68
|
+
id_token_claims: @claims,
|
69
|
+
id_token_header: @header } }
|
70
|
+
end
|
71
|
+
|
72
|
+
DEFAULT_RESPONSE_TYPE = 'code id_token'
|
73
|
+
DEFAULT_RESPONSE_MODE = 'form_post'
|
74
|
+
|
75
|
+
##
|
76
|
+
# Overridden method from OmniAuth::Strategy. This is the first step in the
|
77
|
+
# authentication process.
|
78
|
+
def request_phase
|
79
|
+
redirect authorize_endpoint_url
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Overridden method from OmniAuth::Strategy. This is the second step in
|
84
|
+
# the authentication process. It is called after the user enters
|
85
|
+
# credentials at the authorization endpoint.
|
86
|
+
def callback_phase
|
87
|
+
error = request.params['error_reason'] || request.params['error']
|
88
|
+
fail(OAuthError, error) if error
|
89
|
+
@session_state = request.params['session_state']
|
90
|
+
@id_token = request.params['id_token']
|
91
|
+
@code = request.params['code']
|
92
|
+
@claims, @header = validate_and_parse_id_token(@id_token)
|
93
|
+
validate_chash(@code, @claims, @header)
|
94
|
+
super
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
##
|
100
|
+
# Constructs a one-time-use authorize_endpoint. This method will use
|
101
|
+
# a new nonce on each invocation.
|
102
|
+
#
|
103
|
+
# @return String
|
104
|
+
def authorize_endpoint_url
|
105
|
+
uri = URI(openid_config['authorization_endpoint'])
|
106
|
+
uri.query = URI.encode_www_form(client_id: client_id,
|
107
|
+
redirect_uri: callback_url,
|
108
|
+
response_mode: response_mode,
|
109
|
+
response_type: response_type,
|
110
|
+
nonce: new_nonce)
|
111
|
+
uri.to_s
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# The client id of the calling application. This must be configured where
|
116
|
+
# AzureAD is installed as an OmniAuth strategy.
|
117
|
+
#
|
118
|
+
# @return String
|
119
|
+
def client_id
|
120
|
+
return options.client_id if options.client_id
|
121
|
+
fail StandardError, 'No client_id specified in AzureAD configuration.'
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# The expected id token issuer taken from the discovery endpoint.
|
126
|
+
#
|
127
|
+
# @return String
|
128
|
+
def issuer
|
129
|
+
openid_config['issuer']
|
130
|
+
end
|
131
|
+
|
132
|
+
##
|
133
|
+
# Fetches the current signing keys for Azure AD. Note that there should
|
134
|
+
# always two available, and that they have a 6 week rollover.
|
135
|
+
#
|
136
|
+
# Each key is a hash with the following fields:
|
137
|
+
# kty, use, kid, x5t, n, e, x5c
|
138
|
+
#
|
139
|
+
# @return Array[Hash]
|
140
|
+
def fetch_signing_keys
|
141
|
+
response = JSON.parse(Net::HTTP.get(URI(signing_keys_url)))
|
142
|
+
response['keys']
|
143
|
+
rescue JSON::ParserError
|
144
|
+
raise StandardError, 'Unable to fetch AzureAD signing keys.'
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Fetches the OpenId Connect configuration for the AzureAD tenant. This
|
149
|
+
# contains several import values, including:
|
150
|
+
#
|
151
|
+
# authorization_endpoint
|
152
|
+
# token_endpoint
|
153
|
+
# token_endpoint_auth_methods_supported
|
154
|
+
# jwks_uri
|
155
|
+
# response_types_supported
|
156
|
+
# response_modes_supported
|
157
|
+
# subject_types_supported
|
158
|
+
# id_token_signing_alg_values_supported
|
159
|
+
# scopes_supported
|
160
|
+
# issuer
|
161
|
+
# claims_supported
|
162
|
+
# microsoft_multi_refresh_token
|
163
|
+
# check_session_iframe
|
164
|
+
# end_session_endpoint
|
165
|
+
# userinfo_endpoint
|
166
|
+
#
|
167
|
+
# @return Hash
|
168
|
+
def fetch_openid_config
|
169
|
+
JSON.parse(Net::HTTP.get(URI(openid_config_url)))
|
170
|
+
rescue JSON::ParserError
|
171
|
+
raise StandardError, 'Unable to fetch OpenId configuration for ' \
|
172
|
+
'AzureAD tenant.'
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Generates a new nonce for one time use. Stores it in the session so
|
177
|
+
# multiple users don't share nonces. All nonces should be generated by
|
178
|
+
# this method.
|
179
|
+
#
|
180
|
+
# @return String
|
181
|
+
def new_nonce
|
182
|
+
session['omniauth-azure-activedirectory.nonce'] = SecureRandom.uuid
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# A memoized version of #fetch_openid_config.
|
187
|
+
#
|
188
|
+
# @return Hash
|
189
|
+
def openid_config
|
190
|
+
@openid_config ||= fetch_openid_config
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# The location of the OpenID configuration for the tenant.
|
195
|
+
#
|
196
|
+
# @return String
|
197
|
+
def openid_config_url
|
198
|
+
"https://login.windows.net/#{tenant}/.well-known/openid-configuration"
|
199
|
+
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Returns the most recent nonce for the session and deletes it from the
|
203
|
+
# session.
|
204
|
+
#
|
205
|
+
# @return String
|
206
|
+
def read_nonce
|
207
|
+
session.delete('omniauth-azure-activedirectory.nonce')
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# The response_type that will be set in the authorization request query
|
212
|
+
# parameters. Can be overridden by the client, but it shouldn't need to
|
213
|
+
# be.
|
214
|
+
#
|
215
|
+
# @return String
|
216
|
+
def response_type
|
217
|
+
options[:response_type] || DEFAULT_RESPONSE_TYPE
|
218
|
+
end
|
219
|
+
|
220
|
+
##
|
221
|
+
# The response_mode that will be set in the authorization request query
|
222
|
+
# parameters. Can be overridden by the client, but it shouldn't need to
|
223
|
+
# be.
|
224
|
+
#
|
225
|
+
# @return String
|
226
|
+
def response_mode
|
227
|
+
options[:response_mode] || DEFAULT_RESPONSE_MODE
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# The keys used to sign the id token JWTs. This is just a memoized version
|
232
|
+
# of #fetch_signing_keys.
|
233
|
+
#
|
234
|
+
# @return Array[Hash]
|
235
|
+
def signing_keys
|
236
|
+
@signing_keys ||= fetch_signing_keys
|
237
|
+
end
|
238
|
+
|
239
|
+
##
|
240
|
+
# The location of the public keys of the token signer. This is parsed from
|
241
|
+
# the OpenId config response.
|
242
|
+
#
|
243
|
+
# @return String
|
244
|
+
def signing_keys_url
|
245
|
+
return openid_config['jwks_uri'] if openid_config.include? 'jwks_uri'
|
246
|
+
fail StandardError, 'No jwks_uri in OpenId config response.'
|
247
|
+
end
|
248
|
+
|
249
|
+
##
|
250
|
+
# The tenant of the calling application. Note that this must be
|
251
|
+
# explicitly configured when installing the AzureAD OmniAuth strategy.
|
252
|
+
#
|
253
|
+
# @return String
|
254
|
+
def tenant
|
255
|
+
return options.tenant if options.tenant
|
256
|
+
fail StandardError, 'No tenant specified in AzureAD configuration.'
|
257
|
+
end
|
258
|
+
|
259
|
+
##
|
260
|
+
# Verifies the signature of the id token as well as the exp, nbf, iat,
|
261
|
+
# iss, and aud fields.
|
262
|
+
#
|
263
|
+
# See OpenId Connect Core 3.1.3.7 and 3.2.2.11.
|
264
|
+
#
|
265
|
+
# @return Claims, Header
|
266
|
+
def validate_and_parse_id_token(id_token)
|
267
|
+
# The second parameter is the public key to verify the signature.
|
268
|
+
# However, that key is overridden by the value of the executed block
|
269
|
+
# if one is present.
|
270
|
+
#
|
271
|
+
# If you're thinking that this looks ugly with the raw nil and boolean,
|
272
|
+
# see https://github.com/jwt/ruby-jwt/issues/59.
|
273
|
+
jwt_claims, jwt_header =
|
274
|
+
JWT.decode(id_token, nil, true, verify_options) do |header|
|
275
|
+
# There should always be one key from the discovery endpoint that
|
276
|
+
# matches the id in the JWT header.
|
277
|
+
x5c = (signing_keys.find do |key|
|
278
|
+
key['kid'] == header['kid']
|
279
|
+
end || {})['x5c']
|
280
|
+
if x5c.nil? || x5c.empty?
|
281
|
+
fail JWT::VerificationError,
|
282
|
+
'No keys from key endpoint match the id token'
|
283
|
+
end
|
284
|
+
# The key also contains other fields, such as n and e, that are
|
285
|
+
# redundant. x5c is sufficient to verify the id token.
|
286
|
+
OpenSSL::X509::Certificate.new(JWT.base64url_decode(x5c.first)).public_key
|
287
|
+
end
|
288
|
+
return jwt_claims, jwt_header if jwt_claims['nonce'] == read_nonce
|
289
|
+
fail JWT::DecodeError, 'Returned nonce did not match.'
|
290
|
+
end
|
291
|
+
|
292
|
+
##
|
293
|
+
# Verifies that the c_hash the id token claims matches the authorization
|
294
|
+
# code. See OpenId Connect Core 3.3.2.11.
|
295
|
+
#
|
296
|
+
# @param String code
|
297
|
+
# @param Hash claims
|
298
|
+
# @param Hash header
|
299
|
+
def validate_chash(code, claims, header)
|
300
|
+
# This maps RS256 -> sha256, ES384 -> sha384, etc.
|
301
|
+
algorithm = (header['alg'] || 'RS256').sub(/RS|ES|HS/, 'sha')
|
302
|
+
full_hash = OpenSSL::Digest.new(algorithm).digest code
|
303
|
+
c_hash = JWT.base64url_encode full_hash[0..full_hash.length / 2 - 1]
|
304
|
+
return if c_hash == claims['c_hash']
|
305
|
+
fail JWT::VerificationError,
|
306
|
+
'c_hash in id token does not match auth code.'
|
307
|
+
end
|
308
|
+
|
309
|
+
##
|
310
|
+
# The options passed to the Ruby JWT library to verify the id token.
|
311
|
+
# Note that these are not all the checks we perform. Some (like nonce)
|
312
|
+
# are not handled by the JWT API and are checked manually in
|
313
|
+
# #validate_and_parse_id_token.
|
314
|
+
#
|
315
|
+
# @return Hash
|
316
|
+
def verify_options
|
317
|
+
{ verify_expiration: true,
|
318
|
+
verify_not_before: true,
|
319
|
+
verify_iat: true,
|
320
|
+
verify_iss: true,
|
321
|
+
'iss' => issuer,
|
322
|
+
verify_aud: true,
|
323
|
+
'aud' => client_id }
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
OmniAuth.config.add_camelization 'azure_activedirectory', 'AzureActiveDirectory'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'omniauth/azure_activedirectory/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'omniauth-azure-activedirectory'
|
6
|
+
s.version = OmniAuth::AzureActiveDirectory::VERSION
|
7
|
+
s.author = 'Microsoft Corporation'
|
8
|
+
s.email = 'nugetaad@microsoft.com'
|
9
|
+
s.summary = 'Azure Active Directory strategy for OmniAuth'
|
10
|
+
s.description = 'Allows developers to authenticate to AAD'
|
11
|
+
s.homepage = 'https://github.com/AzureAD/omniauth-azure-activedirectory'
|
12
|
+
s.license = 'MIT'
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
|
17
|
+
s.add_runtime_dependency 'jwt', '~> 1.5'
|
18
|
+
s.add_runtime_dependency 'omniauth', '~> 1.1'
|
19
|
+
|
20
|
+
s.add_development_dependency 'rake', '~> 10.4'
|
21
|
+
s.add_development_dependency 'rspec', '~> 3.3'
|
22
|
+
s.add_development_dependency 'rubocop', '~> 0.32'
|
23
|
+
s.add_development_dependency 'simplecov', '~> 0.10'
|
24
|
+
s.add_development_dependency 'webmock', '~> 1.21'
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyJ9.eyJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9idW5jaC1vZi1yYW5kb20tY2hhcnMiLCJuYW1lIjoiSm9obiBTbWl0aCIsImF1ZCI6InRoZSBjbGllbnQgaWQiLCJub25jZSI6Im15IG5vbmNlIiwiZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6InNtaXRoIiwiZW1haWwiOiJqc21pdGhAY29udG9zby5jb20iLCJjX2hhc2giOiJWcFRRaWk1VF84cmd3eEEtV3RiMkJ3In0.Xz9SL1dm9xeJ3YtBIwSpL7SHEMr5lsL32mkJIugoAt7rNhj2ZauN77_N3skU9FIRTVb_XBFHrLo1AXion7RWoOGAMk8xnuQRlhamGoWsjttWE9oO6J6kuQPSDBvLTA88UqLoGNezDwFNfgUFQq-66m33ZWdkiNOFoFZ_In6DtAwxHZZUys-KoYD3iCbviUoBzU57aV-SBsWyComq39pDGpw03qZoa_xgRfujdVHG1DKlO5VG79kUE3ySYWJyBYVKUdAzjH1iotjpPA1svtqytn4CUldAMi4nnf7iq5SCJMb4ucu0mN6AhJH9ktY--fGY6_OidyiDe4F57ZzLw-3jOQ
|
@@ -0,0 +1 @@
|
|
1
|
+
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyJ9.eyJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9idW5jaC1vZi1yYW5kb20tY2hhcnMiLCJuYW1lIjoiSm9obiBTbWl0aCIsImF1ZCI6Im5vdCB0aGUgY2xpZW50IGlkIiwibm9uY2UiOiJteSBub25jZSIsImdpdmVuX25hbWUiOiJKb2huIiwiZmFtaWx5X25hbWUiOiJzbWl0aCIsImVtYWlsIjoianNtaXRoQGNvbnRvc28uY29tIn0.gGCFTcGDBb2P5tPRj2ojUUiwOJoSslQlxEVTElZY6FCzCZzcypsnrYOB9Adkztp2AWF4wW9fT58lqXwaahKquXtK4wyK4KoNBxXBhS4sDMeNpVkK4914tT_6gecvyUsI_tlJaS0epd5c0mN9-1QjgvNEirY1L-XYaT290LmLYVYIFTEJXoSlnwvv081k0txdJZKr14JXd_bSLUbhGSd-NcGZkJuVmg2F_C65zd1wUsQOkV2iVdJ-ycaDJklv8-DFfDFIHQio8S9yqyieHwArRmTW9HzcoHhWBh2MIItszoTSbmQEF062NtNBPW8gyk1OSot5X9klJUhgPAAFqJ0TJQ
|
@@ -0,0 +1 @@
|
|
1
|
+
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyJ9.eyJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9idW5jaC1vZi1yYW5kb20tY2hhcnMiLCJuYW1lIjoiSm9obiBTbWl0aCIsImF1ZCI6InRoZSBjbGllbnQgaWQiLCJub25jZSI6Im15IG5vbmNlIiwiZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6InNtaXRoIiwiZW1haWwiOiJqc21pdGhAY29udG9zby5jb20iLCJjX2hhc2giOiI1WEhDdk9qcUgtbnJBXzNXNUJYaWJnIn0.EHPFrxMbr2EH1IZ15F3oP1yvrukadY4ggZSOxm625qPoMxfhv-QzFm0YMhkAG0cLM_LSHi_RgedDwTGuzOtIWqmheYzydnhtbIBeKmx0RSgdob6WeiTZwJ93VRiV4q82Qda41JaaIl_wdWd4lVyVstd9o9jPYMtKEVLgaNDrtHt6pPxEGCVraiaM6tVyKc5XIHu3wNaqle5UZZREU6oirwTCUhXDZkz1g5qY2-aWUdfFVsElSarJuMcxGDPD20hvx7T3D7SCHAF8WhKw3AwQyrodKWCo3cqDOz6vHymb_-ELkJc14GMbtJiyrf6XYySZZoseoI_WBDmLfKcK637xCw
|
@@ -0,0 +1 @@
|
|
1
|
+
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMyJ9.eyJpc3MiOiJodHRwczovL3N0cy5pbXBvc3Rlci5uZXQvYnVuY2gtb2YtcmFuZG9tLWNoYXJzIiwibmFtZSI6IkpvaG4gU21pdGgiLCJhdWQiOiJ0aGUgY2xpZW50IGlkIiwibm9uY2UiOiJteSBub25jZSIsImdpdmVuX25hbWUiOiJKb2huIiwiZmFtaWx5X25hbWUiOiJzbWl0aCIsImVtYWlsIjoianNtaXRoQGNvbnRvc28uY29tIn0.fwnJuRsif_Td3MfXoyADHidYJyPFdWSBBoLbVAu4Lz3-pmSln9Vgxl5KowqEKq2LX5n0aqyWVGLcoT-_G_PNXuizuNmssv5vreKLvDMpsFXt2irdwGYDCRki7KQPBk3bn12YjBzE2EqiRy7dTEG_0vWoh1RqoNP72BBL8xYQUlIOFleZhT5KGNYbh7rvcmDq7aA-xdaXT3QJfHCHpitW_zVzZ5Gok_awcdx_v3r3eFbG2IT0PfmT40Ljia0aP2i60KgsOLLHarYO51KFNDEfr1pUDf4IweaEzstbVLwk-_5ulJ5QgByhNJrmWDfrGeCQRk0SO2XX-EUsVn5ySVJ5CQ
|
@@ -0,0 +1 @@
|
|
1
|
+
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImFiYzEyMzQifQ.eyJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9idW5jaC1vZi1yYW5kb20tY2hhcnMiLCJuYW1lIjoiSm9obiBTbWl0aCIsImF1ZCI6InRoZSBjbGllbnQgaWQiLCJub25jZSI6Im15IG5vbmNlIiwiZ2l2ZW5fbmFtZSI6IkpvaG4iLCJmYW1pbHlfbmFtZSI6InNtaXRoIiwiZW1haWwiOiJqc21pdGhAY29udG9zby5jb20iLCJjX2hhc2giOiI1WEhDdk9qcUgtbnJBXzNXNUJYaWJnIn0.gWGBc9rH30SN17Ikm1CjqIYAyzFHX0yeRQu85sVYLE3r5k26bjS3R6rTJcCQlYqHPRdoPcnkUgT1QVbdThw34ICrODoavs7I5QYEn_jKP9zM4UJEKQaCLBAtitzrk1KDEf0GLcNKif-MYu7MiQfoOzwCGWfIs-vgqk4lv0JUs9OlSLp5LHru7G3jKy6Qswbrpxpjzm9I8BnKEdhUfhz4P6wIf9KLMmhgeGQdQ6wBuxPmOf9r6EKIij2AENhFp1qP90m8kXq9tIt5FZFjwIs_G6spLl0gQXyx0qC8rP5JTkqwrBUieWU-BRqVdax8YxA0iDKzZyfsMV92yVcZT6S_NQ
|