adal 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 +5 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +7 -0
- data/Gemfile +25 -0
- data/LICENSE.txt +21 -0
- data/README.md +97 -0
- data/Rakefile +39 -0
- data/adal.gemspec +52 -0
- data/contributing.md +127 -0
- data/lib/adal.rb +24 -0
- data/lib/adal/authentication_context.rb +202 -0
- data/lib/adal/authentication_parameters.rb +126 -0
- data/lib/adal/authority.rb +165 -0
- data/lib/adal/cache_driver.rb +171 -0
- data/lib/adal/cached_token_response.rb +190 -0
- data/lib/adal/client_assertion.rb +63 -0
- data/lib/adal/client_assertion_certificate.rb +89 -0
- data/lib/adal/client_credential.rb +46 -0
- data/lib/adal/core_ext.rb +26 -0
- data/lib/adal/core_ext/hash.rb +34 -0
- data/lib/adal/jwt_parameters.rb +39 -0
- data/lib/adal/logger.rb +90 -0
- data/lib/adal/logging.rb +98 -0
- data/lib/adal/memory_cache.rb +95 -0
- data/lib/adal/mex_request.rb +52 -0
- data/lib/adal/mex_response.rb +141 -0
- data/lib/adal/noop_cache.rb +38 -0
- data/lib/adal/oauth_request.rb +76 -0
- data/lib/adal/request_parameters.rb +48 -0
- data/lib/adal/self_signed_jwt_factory.rb +96 -0
- data/lib/adal/templates/rst.13.xml.erb +35 -0
- data/lib/adal/templates/rst.2005.xml.erb +32 -0
- data/lib/adal/token_request.rb +231 -0
- data/lib/adal/token_response.rb +144 -0
- data/lib/adal/user_assertion.rb +57 -0
- data/lib/adal/user_credential.rb +152 -0
- data/lib/adal/user_identifier.rb +83 -0
- data/lib/adal/user_information.rb +49 -0
- data/lib/adal/util.rb +49 -0
- data/lib/adal/version.rb +36 -0
- data/lib/adal/wstrust_request.rb +100 -0
- data/lib/adal/wstrust_response.rb +168 -0
- data/lib/adal/xml_namespaces.rb +64 -0
- data/samples/authorization_code_example/README.md +10 -0
- data/samples/authorization_code_example/web_app.rb +139 -0
- data/samples/client_assertion_certificate_example/README.md +42 -0
- data/samples/client_assertion_certificate_example/app.rb +55 -0
- data/samples/on_behalf_of_example/README.md +35 -0
- data/samples/on_behalf_of_example/native_app.rb +52 -0
- data/samples/on_behalf_of_example/web_api.rb +71 -0
- data/samples/user_credentials_example/README.md +7 -0
- data/samples/user_credentials_example/app.rb +52 -0
- data/spec/adal/authentication_context_spec.rb +186 -0
- data/spec/adal/authentication_parameters_spec.rb +107 -0
- data/spec/adal/authority_spec.rb +122 -0
- data/spec/adal/cache_driver_spec.rb +191 -0
- data/spec/adal/cached_token_response_spec.rb +148 -0
- data/spec/adal/client_assertion_certificate_spec.rb +113 -0
- data/spec/adal/client_assertion_spec.rb +38 -0
- data/spec/adal/core_ext/hash_spec.rb +47 -0
- data/spec/adal/logging_spec.rb +48 -0
- data/spec/adal/memory_cache_spec.rb +107 -0
- data/spec/adal/mex_request_spec.rb +57 -0
- data/spec/adal/mex_response_spec.rb +143 -0
- data/spec/adal/self_signed_jwt_factory_spec.rb +63 -0
- data/spec/adal/token_request_spec.rb +150 -0
- data/spec/adal/token_response_spec.rb +102 -0
- data/spec/adal/user_credential_spec.rb +125 -0
- data/spec/adal/user_identifier_spec.rb +115 -0
- data/spec/adal/wstrust_request_spec.rb +51 -0
- data/spec/adal/wstrust_response_spec.rb +152 -0
- data/spec/fixtures/mex/insecureaddress.xml +924 -0
- data/spec/fixtures/mex/invalid_namespaces.xml +916 -0
- data/spec/fixtures/mex/malformed.xml +914 -0
- data/spec/fixtures/mex/microsoft.xml +916 -0
- data/spec/fixtures/mex/multiple_endpoints.xml +922 -0
- data/spec/fixtures/mex/no_matching_bindings.xml +916 -0
- data/spec/fixtures/mex/no_username_token_policies.xml +914 -0
- data/spec/fixtures/mex/no_wstrust_endpoints.xml +838 -0
- data/spec/fixtures/mex/only_13.xml +842 -0
- data/spec/fixtures/mex/only_2005.xml +842 -0
- data/spec/fixtures/oauth/error.json +1 -0
- data/spec/fixtures/oauth/success.json +1 -0
- data/spec/fixtures/oauth/success_with_id_token.json +1 -0
- data/spec/fixtures/wstrust/error.xml +24 -0
- data/spec/fixtures/wstrust/invalid_namespaces.xml +136 -0
- data/spec/fixtures/wstrust/missing_security_tokens.xml +90 -0
- data/spec/fixtures/wstrust/success.xml +136 -0
- data/spec/fixtures/wstrust/token.xml +1 -0
- data/spec/fixtures/wstrust/too_many_security_tokens.xml +219 -0
- data/spec/fixtures/wstrust/unrecognized_token_type.xml +136 -0
- data/spec/fixtures/wstrust/wstrust.13.xml +1 -0
- data/spec/fixtures/wstrust/wstrust.2005.xml +89 -0
- data/spec/spec_helper.rb +53 -0
- data/spec/support/fake_data.rb +40 -0
- data/spec/support/fake_token_endpoint.rb +108 -0
- metadata +265 -0
@@ -0,0 +1,190 @@
|
|
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 ADAL
|
24
|
+
# Proxy object for a token response with metadata.
|
25
|
+
class CachedTokenResponse
|
26
|
+
attr_reader :authority
|
27
|
+
attr_reader :client_id
|
28
|
+
attr_reader :token_response
|
29
|
+
|
30
|
+
##
|
31
|
+
# Constructs a new CachedTokenResponse.
|
32
|
+
#
|
33
|
+
# @param ClientCredential|ClientAssertion|ClientAssertionCertificate
|
34
|
+
# The credentials of the calling client application.
|
35
|
+
# @param Authority authority
|
36
|
+
# The ADAL::Authority object that the response was retrieved from.
|
37
|
+
# @param SuccessResponse token_response
|
38
|
+
# The token response to be cached.
|
39
|
+
def initialize(client, authority, token_response)
|
40
|
+
unless token_response.instance_of? SuccessResponse
|
41
|
+
fail ArgumentError, 'Only SuccessResponses can be cached.'
|
42
|
+
end
|
43
|
+
@authority = authority
|
44
|
+
if client.respond_to? :client_id
|
45
|
+
@client = client
|
46
|
+
@client_id = client.client_id
|
47
|
+
else
|
48
|
+
@client = ClientCredential.new(client)
|
49
|
+
@client_id = client
|
50
|
+
end
|
51
|
+
@token_response = token_response
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Converts the fields in this object and its proxied SuccessResponse into
|
56
|
+
# a JSON string.
|
57
|
+
#
|
58
|
+
# @param JSON::Ext::Generator::State
|
59
|
+
# We don't care about the state, but JSON::unparse requires this.
|
60
|
+
# @return String
|
61
|
+
def to_json(_ = nil)
|
62
|
+
JSON.unparse(authority: [authority.host, authority.tenant],
|
63
|
+
client_id: client_id,
|
64
|
+
token_response: token_response)
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Reconstructs an object from JSON that was serialized with
|
69
|
+
# CachedTokenResponse#to_json.
|
70
|
+
#
|
71
|
+
# @param JSON raw_json
|
72
|
+
# @return CachedTokenResponse
|
73
|
+
def self.from_json(json)
|
74
|
+
json = JSON.parse(json) if json.instance_of? String
|
75
|
+
CachedTokenResponse.new(json['client_id'],
|
76
|
+
Authority.new(*json['authority']),
|
77
|
+
SuccessResponse.new(json['token_response']))
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Determines if self can be used to refresh other.
|
82
|
+
#
|
83
|
+
# @param CachedTokenResponse other
|
84
|
+
# @return Boolean
|
85
|
+
def can_refresh?(other)
|
86
|
+
mrrt? && (authority == other.authority) &&
|
87
|
+
(user_info == other.user_info) && (client_id == other.client_id)
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# If the access token is within the expiration buffer of expiring, an
|
92
|
+
# attempt will be made to retrieve a new token with the refresh token.
|
93
|
+
#
|
94
|
+
# @param Fixnum expiration_buffer_sec
|
95
|
+
# The number of seconds to use as leeway in determining if the token is
|
96
|
+
# expired. A positive buffer will refresh the token early while a negative
|
97
|
+
# buffer will refresh it late. Used to counter clock skew and network
|
98
|
+
# latency.
|
99
|
+
# @return Boolean
|
100
|
+
# True if the token is still valid (even if it was refreshed). False if
|
101
|
+
# the token is expired an unable to be refreshed.
|
102
|
+
def validate(expiration_buffer_sec = 0)
|
103
|
+
return true if (Time.now + expiration_buffer_sec).to_i < expires_on
|
104
|
+
unless refresh_token
|
105
|
+
logger.verbose('Cached token is almost expired but no refresh token ' \
|
106
|
+
'is available.')
|
107
|
+
return false
|
108
|
+
end
|
109
|
+
logger.verbose('Cached token is almost expired, attempting to refresh ' \
|
110
|
+
' with refresh token.')
|
111
|
+
refresh_response = refresh
|
112
|
+
if refresh_response.instance_of? SuccessResponse
|
113
|
+
logger.verbose('Successfully refreshed token in cache.')
|
114
|
+
@token_response = refresh_response
|
115
|
+
true
|
116
|
+
else
|
117
|
+
logger.warn('Failed to refresh token in cache with refresh token.')
|
118
|
+
false
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Attempts to refresh the access token for a given resource. Note that you
|
124
|
+
# can call this method with a different resource even if the token is not
|
125
|
+
# an MRRT, but it will fail
|
126
|
+
#
|
127
|
+
# @param String resource
|
128
|
+
# The resource that the new access token is beign requested for. Defaults
|
129
|
+
# to using the same resource as the original token.
|
130
|
+
# @return TokenResponse
|
131
|
+
def refresh(new_resource = resource)
|
132
|
+
token_response = TokenRequest
|
133
|
+
.new(authority, @client)
|
134
|
+
.get_with_refresh_token(refresh_token, new_resource)
|
135
|
+
if token_response.instance_of? SuccessResponse
|
136
|
+
token_response.parse_id_token(id_token)
|
137
|
+
end
|
138
|
+
token_response
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Changes the refresh token of the underlying token response.
|
143
|
+
#
|
144
|
+
# @param String token
|
145
|
+
def refresh_token=(token)
|
146
|
+
token_response.instance_variable_set(:@refresh_token, token)
|
147
|
+
logger.verbose("Updated the refresh token for #{token_response}.")
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Is the token a Multi Resource Refresh Token?
|
152
|
+
#
|
153
|
+
# @return Boolean
|
154
|
+
def mrrt?
|
155
|
+
token_response.refresh_token && token_response.resource
|
156
|
+
end
|
157
|
+
|
158
|
+
## Since the token cache may be implemented by the user of this library,
|
159
|
+
## all means of checking equality must be consistent.
|
160
|
+
|
161
|
+
def ==(other)
|
162
|
+
[:authority, :client_id, :token_response].all? do |field|
|
163
|
+
(other.respond_to? field) && (send(field) == other.send(field))
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def eql?(other)
|
168
|
+
self == other
|
169
|
+
end
|
170
|
+
|
171
|
+
def hash
|
172
|
+
[authority, client_id, token_response].hash
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
# CachedTokenResponse is just a proxy for TokenResponse.
|
178
|
+
def method_missing(method, *args, &block)
|
179
|
+
if token_response.respond_to?(method)
|
180
|
+
token_response.send(method, *args, &block)
|
181
|
+
else
|
182
|
+
super(method)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def respond_to_missing?(method, include_private = false)
|
187
|
+
token_response.respond_to?(method, include_private) || super
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,63 @@
|
|
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_relative './request_parameters'
|
24
|
+
require_relative './token_request'
|
25
|
+
require_relative './util'
|
26
|
+
|
27
|
+
module ADAL
|
28
|
+
# A client credential that consists of the client id and a JWT bearer
|
29
|
+
# assertion. The type is 'urn:ietf:params:oauth:token-type:jwt'.
|
30
|
+
class ClientAssertion
|
31
|
+
include TokenRequest::GrantType
|
32
|
+
include RequestParameters
|
33
|
+
include Util
|
34
|
+
|
35
|
+
attr_reader :assertion
|
36
|
+
attr_reader :assertion_type
|
37
|
+
attr_reader :client_id
|
38
|
+
|
39
|
+
##
|
40
|
+
# Creates a new ClientAssertion.
|
41
|
+
#
|
42
|
+
# @param [String] client_id
|
43
|
+
# The client id of the calling application.
|
44
|
+
# @param [String] assertion
|
45
|
+
# The JWT used as a credential.
|
46
|
+
def initialize(client_id, assertion, assertion_type = JWT_BEARER)
|
47
|
+
fail_if_arguments_nil(client_id, assertion, assertion_type)
|
48
|
+
@assertion = assertion
|
49
|
+
@assertion_type = assertion_type
|
50
|
+
@client_id = client_id
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# The relavent parameters from this credential for OAuth.
|
55
|
+
#
|
56
|
+
# @return Hash
|
57
|
+
def request_params
|
58
|
+
{ CLIENT_ID => @client_id,
|
59
|
+
CLIENT_ASSERTION_TYPE => @assertion_type,
|
60
|
+
CLIENT_ASSERTION => @assertion }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,89 @@
|
|
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 'openssl'
|
24
|
+
|
25
|
+
module ADAL
|
26
|
+
# An assertion made by a client with an X509 certificate. This requires both
|
27
|
+
# the public and private keys. Technically it only requires the thumbprint
|
28
|
+
# of the public key, however OpenSSL's object model does not include
|
29
|
+
# thumbprints.
|
30
|
+
class ClientAssertionCertificate
|
31
|
+
include RequestParameters
|
32
|
+
|
33
|
+
MIN_KEY_SIZE_BITS = 2014
|
34
|
+
|
35
|
+
attr_reader :certificate
|
36
|
+
attr_reader :client_id
|
37
|
+
|
38
|
+
##
|
39
|
+
# Creates a new ClientAssertionCertificate.
|
40
|
+
#
|
41
|
+
# @param Authority authority
|
42
|
+
# The authority object that will recognize this certificate.
|
43
|
+
# @param [String] client_id
|
44
|
+
# The client id of the calling application.
|
45
|
+
# @param [OpenSSL::PKCS12] pkcs12_file
|
46
|
+
# The PKCS12 file containing the certificate and private key.
|
47
|
+
def initialize(authority, client_id, pkcs12_file)
|
48
|
+
unless pkcs12_file.is_a? OpenSSL::PKCS12
|
49
|
+
fail ArgumentError, 'Only PKCS12 file format is supported.'
|
50
|
+
end
|
51
|
+
@authority = authority
|
52
|
+
@certificate = pkcs12_file.certificate
|
53
|
+
@client_id = client_id.to_s
|
54
|
+
@private_key = pkcs12_file.key
|
55
|
+
validate_certificate_and_key(@certificate, @private_key)
|
56
|
+
end
|
57
|
+
|
58
|
+
# The relevant parameters from this credential for OAuth.
|
59
|
+
def request_params
|
60
|
+
jwt_assertion = SelfSignedJwtFactory
|
61
|
+
.new(@client_id, @authority.token_endpoint)
|
62
|
+
.create_and_sign_jwt(@certificate, @private_key)
|
63
|
+
ClientAssertion.new(client_id, jwt_assertion).request_params
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# @param [OpenSSL::X509::Certificate] certificate
|
69
|
+
# @return [Fixnum] The number of bits in the public key.
|
70
|
+
def public_key_size_bits(certificate)
|
71
|
+
certificate.public_key.n.num_bytes * 8
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# In general, Ruby code is very loose about types. However, since we are
|
76
|
+
# dealing with sensitive information here, we will be a little bit stricter
|
77
|
+
# on type safety.
|
78
|
+
def validate_certificate_and_key(certificate, private_key)
|
79
|
+
if !certificate.is_a? OpenSSL::X509::Certificate
|
80
|
+
fail ArgumentError, 'certificate must be an OpenSSL::X509::Certificate.'
|
81
|
+
elsif !private_key.is_a? OpenSSL::PKey::RSA
|
82
|
+
fail ArgumentError, 'private_key must be an OpenSSL::PKey::RSA.'
|
83
|
+
elsif public_key_size_bits(certificate) < MIN_KEY_SIZE_BITS
|
84
|
+
fail ArgumentError, 'certificate must contain a public key of at ' \
|
85
|
+
"least #{MIN_KEY_SIZE_BITS} bits."
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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_relative './request_parameters'
|
24
|
+
require_relative './util'
|
25
|
+
|
26
|
+
module ADAL
|
27
|
+
# A wrapper object for a client id and secret.
|
28
|
+
class ClientCredential
|
29
|
+
include RequestParameters
|
30
|
+
include Util
|
31
|
+
|
32
|
+
attr_reader :client_id
|
33
|
+
attr_reader :client_secret
|
34
|
+
|
35
|
+
def initialize(client_id, client_secret = nil)
|
36
|
+
fail_if_arguments_nil(client_id)
|
37
|
+
@client_id = client_id
|
38
|
+
@client_secret = client_secret
|
39
|
+
end
|
40
|
+
|
41
|
+
# The relavent parameters from this credential for OAuth.
|
42
|
+
def request_params
|
43
|
+
{ CLIENT_ID => @client_id, CLIENT_SECRET => @client_secret }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,26 @@
|
|
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
|
+
# All of the refinements used in ADAL. They are all in the namespace
|
24
|
+
# ADAL::CoreExt and will only be applied to files that start with ADAL::CoreExt
|
25
|
+
# before opening any module or class.
|
26
|
+
require_relative './core_ext/hash'
|
@@ -0,0 +1,34 @@
|
|
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 ADAL
|
24
|
+
# Adds helper methods to Hash. These are standard in Rails and are
|
25
|
+
# commonplace in the Ruby community.
|
26
|
+
module CoreExt
|
27
|
+
# Same as #merge, but values in other_hash are prioritized over self.
|
28
|
+
refine Hash do
|
29
|
+
def reverse_merge(other_hash)
|
30
|
+
other_hash.merge(self)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|