custom-adal 1.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.
Files changed (98) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rubocop.yml +7 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +25 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +106 -0
  8. data/Rakefile +39 -0
  9. data/adal.gemspec +52 -0
  10. data/contributing.md +127 -0
  11. data/lib/adal/authentication_context.rb +202 -0
  12. data/lib/adal/authentication_parameters.rb +126 -0
  13. data/lib/adal/authority.rb +165 -0
  14. data/lib/adal/cache_driver.rb +171 -0
  15. data/lib/adal/cached_token_response.rb +190 -0
  16. data/lib/adal/client_assertion.rb +63 -0
  17. data/lib/adal/client_assertion_certificate.rb +89 -0
  18. data/lib/adal/client_credential.rb +46 -0
  19. data/lib/adal/core_ext/hash.rb +34 -0
  20. data/lib/adal/core_ext.rb +26 -0
  21. data/lib/adal/jwt_parameters.rb +39 -0
  22. data/lib/adal/logger.rb +90 -0
  23. data/lib/adal/logging.rb +98 -0
  24. data/lib/adal/memory_cache.rb +95 -0
  25. data/lib/adal/mex_request.rb +52 -0
  26. data/lib/adal/mex_response.rb +141 -0
  27. data/lib/adal/noop_cache.rb +38 -0
  28. data/lib/adal/oauth_request.rb +76 -0
  29. data/lib/adal/request_parameters.rb +48 -0
  30. data/lib/adal/self_signed_jwt_factory.rb +96 -0
  31. data/lib/adal/templates/rst.13.xml.erb +35 -0
  32. data/lib/adal/templates/rst.2005.xml.erb +32 -0
  33. data/lib/adal/token_request.rb +231 -0
  34. data/lib/adal/token_response.rb +144 -0
  35. data/lib/adal/user_assertion.rb +57 -0
  36. data/lib/adal/user_credential.rb +152 -0
  37. data/lib/adal/user_identifier.rb +83 -0
  38. data/lib/adal/user_information.rb +49 -0
  39. data/lib/adal/util.rb +49 -0
  40. data/lib/adal/version.rb +36 -0
  41. data/lib/adal/wstrust_request.rb +100 -0
  42. data/lib/adal/wstrust_response.rb +168 -0
  43. data/lib/adal/xml_namespaces.rb +64 -0
  44. data/lib/adal.rb +24 -0
  45. data/samples/authorization_code_example/README.md +10 -0
  46. data/samples/authorization_code_example/web_app.rb +139 -0
  47. data/samples/client_assertion_certificate_example/README.md +42 -0
  48. data/samples/client_assertion_certificate_example/app.rb +55 -0
  49. data/samples/on_behalf_of_example/README.md +35 -0
  50. data/samples/on_behalf_of_example/native_app.rb +52 -0
  51. data/samples/on_behalf_of_example/web_api.rb +71 -0
  52. data/samples/user_credentials_example/README.md +7 -0
  53. data/samples/user_credentials_example/app.rb +52 -0
  54. data/spec/adal/authentication_context_spec.rb +186 -0
  55. data/spec/adal/authentication_parameters_spec.rb +107 -0
  56. data/spec/adal/authority_spec.rb +122 -0
  57. data/spec/adal/cache_driver_spec.rb +191 -0
  58. data/spec/adal/cached_token_response_spec.rb +148 -0
  59. data/spec/adal/client_assertion_certificate_spec.rb +113 -0
  60. data/spec/adal/client_assertion_spec.rb +38 -0
  61. data/spec/adal/core_ext/hash_spec.rb +47 -0
  62. data/spec/adal/logging_spec.rb +48 -0
  63. data/spec/adal/memory_cache_spec.rb +107 -0
  64. data/spec/adal/mex_request_spec.rb +57 -0
  65. data/spec/adal/mex_response_spec.rb +143 -0
  66. data/spec/adal/self_signed_jwt_factory_spec.rb +63 -0
  67. data/spec/adal/token_request_spec.rb +150 -0
  68. data/spec/adal/token_response_spec.rb +102 -0
  69. data/spec/adal/user_credential_spec.rb +125 -0
  70. data/spec/adal/user_identifier_spec.rb +115 -0
  71. data/spec/adal/wstrust_request_spec.rb +51 -0
  72. data/spec/adal/wstrust_response_spec.rb +152 -0
  73. data/spec/fixtures/mex/insecureaddress.xml +924 -0
  74. data/spec/fixtures/mex/invalid_namespaces.xml +916 -0
  75. data/spec/fixtures/mex/malformed.xml +914 -0
  76. data/spec/fixtures/mex/microsoft.xml +916 -0
  77. data/spec/fixtures/mex/multiple_endpoints.xml +922 -0
  78. data/spec/fixtures/mex/no_matching_bindings.xml +916 -0
  79. data/spec/fixtures/mex/no_username_token_policies.xml +914 -0
  80. data/spec/fixtures/mex/no_wstrust_endpoints.xml +838 -0
  81. data/spec/fixtures/mex/only_13.xml +842 -0
  82. data/spec/fixtures/mex/only_2005.xml +842 -0
  83. data/spec/fixtures/oauth/error.json +1 -0
  84. data/spec/fixtures/oauth/success.json +1 -0
  85. data/spec/fixtures/oauth/success_with_id_token.json +1 -0
  86. data/spec/fixtures/wstrust/error.xml +24 -0
  87. data/spec/fixtures/wstrust/invalid_namespaces.xml +136 -0
  88. data/spec/fixtures/wstrust/missing_security_tokens.xml +90 -0
  89. data/spec/fixtures/wstrust/success.xml +136 -0
  90. data/spec/fixtures/wstrust/token.xml +1 -0
  91. data/spec/fixtures/wstrust/too_many_security_tokens.xml +219 -0
  92. data/spec/fixtures/wstrust/unrecognized_token_type.xml +136 -0
  93. data/spec/fixtures/wstrust/wstrust.13.xml +1 -0
  94. data/spec/fixtures/wstrust/wstrust.2005.xml +89 -0
  95. data/spec/spec_helper.rb +53 -0
  96. data/spec/support/fake_data.rb +40 -0
  97. data/spec/support/fake_token_endpoint.rb +108 -0
  98. metadata +264 -0
@@ -0,0 +1,141 @@
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 './logging'
24
+ require_relative './xml_namespaces'
25
+
26
+ require 'nokogiri'
27
+ require 'uri'
28
+
29
+ module ADAL
30
+ # Relevant fields from a Mex response.
31
+ class MexResponse
32
+ include XmlNamespaces
33
+
34
+ class << self
35
+ include Logging
36
+ end
37
+
38
+ class MexError < StandardError; end
39
+
40
+ POLICY_ID_XPATH =
41
+ '//wsdl:definitions/wsp:Policy[./wsp:ExactlyOne/wsp:All/sp:SignedSuppor' \
42
+ 'tingTokens/wsp:Policy/sp:UsernameToken/wsp:Policy/sp:WssUsernameToken1' \
43
+ '0]/@u:Id|//wsdl:definitions/wsp:Policy[./wsp:ExactlyOne/wsp:All/ssp:Si' \
44
+ 'gnedEncryptedSupportingTokens/wsp:Policy/ssp:UsernameToken/wsp:Policy/' \
45
+ 'ssp:WssUsernameToken10]/@u:Id'
46
+ BINDING_XPATH = '//wsdl:definitions/wsdl:binding[./wsp:PolicyReference]'
47
+ PORT_XPATH = '//wsdl:definitions/wsdl:service/wsdl:port'
48
+ ADDRESS_XPATH = './soap12:address/@location'
49
+
50
+ ##
51
+ # Parses the XML string response from the Metadata Exchange endpoint into
52
+ # a MexResponse object.
53
+ #
54
+ # @param String response
55
+ # @return MexResponse
56
+ def self.parse(response)
57
+ xml = Nokogiri::XML(response)
58
+ policy_ids = parse_policy_ids(xml)
59
+ bindings = parse_bindings(xml, policy_ids)
60
+ endpoint, binding = parse_endpoint_and_binding(xml, bindings)
61
+ MexResponse.new(endpoint, binding)
62
+ end
63
+
64
+ # @param Nokogiri::XML::Document xml
65
+ # @param Array[String] policy_ids
66
+ # @return Array[String]
67
+ def self.parse_bindings(xml, policy_ids)
68
+ matching_bindings = xml.xpath(BINDING_XPATH, NAMESPACES).map do |node|
69
+ reference_uri = node.xpath('./wsp:PolicyReference/@URI', NAMESPACES)
70
+ node.xpath('./@name').to_s if policy_ids.include? reference_uri.to_s
71
+ end.compact
72
+ fail MexError, 'No matching bindings found.' if matching_bindings.empty?
73
+ matching_bindings
74
+ end
75
+ private_class_method :parse_bindings
76
+
77
+ # @param Nokogiri::XML::Document xml
78
+ # @param Array[String] bindings
79
+ # @return Array[[String, String]]
80
+ def self.parse_all_endpoints(xml, bindings)
81
+ endpoints = xml.xpath(PORT_XPATH, NAMESPACES).map do |node|
82
+ binding = node.attr('binding').split(':').last
83
+ if bindings.include? binding
84
+ [node.xpath(ADDRESS_XPATH, NAMESPACES).to_s, binding]
85
+ end
86
+ end.compact
87
+ endpoints
88
+ end
89
+ private_class_method :parse_all_endpoints
90
+
91
+ # @param Nokogiri::XML::Document xml
92
+ # @param Array[String] bindings
93
+ # @return [String, String]
94
+ def self.parse_endpoint_and_binding(xml, bindings)
95
+ endpoints = parse_all_endpoints(xml, bindings)
96
+ case endpoints.size
97
+ when 0
98
+ fail MexError, 'No valid WS-Trust endpoints found.'
99
+ when 1
100
+ else
101
+ logger.info('Multiple WS-Trust endpoints were found in the mex ' \
102
+ 'response. Only one was used.')
103
+ end
104
+ prefer_13(endpoints).first
105
+ end
106
+ private_class_method :parse_endpoint_and_binding
107
+
108
+ # @param Nokogiri::XML::Document xml
109
+ # @return Array[String]
110
+ def self.parse_policy_ids(xml)
111
+ policy_ids = xml.xpath(POLICY_ID_XPATH, NAMESPACES)
112
+ .map { |attr| "\##{attr.value}" }
113
+ fail MexError, 'No username token policy nodes.' if policy_ids.empty?
114
+ policy_ids
115
+ end
116
+ private_class_method :parse_policy_ids
117
+
118
+ # @param Array[String, String] endpoints
119
+ # @return Array[String, String] endpoints
120
+ def self.prefer_13(endpoints)
121
+ only13 = endpoints.select { |_, b| BINDING_TO_ACTION[b] == WSTRUST_13 }
122
+ only13.empty? ? endpoints : only13
123
+ end
124
+ private_class_method :prefer_13
125
+
126
+ attr_reader :action
127
+ attr_reader :wstrust_url
128
+
129
+ ##
130
+ # Constructs a new MexResponse.
131
+ #
132
+ # @param String|URI wstrust_url
133
+ # @param String action
134
+ def initialize(wstrust_url, binding)
135
+ @action = BINDING_TO_ACTION[binding]
136
+ @wstrust_url = URI.parse(wstrust_url.to_s)
137
+ return if @wstrust_url.instance_of? URI::HTTPS
138
+ fail ArgumentError, 'Mex is only done over HTTPS.'
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,38 @@
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
+ # A cache implementation that holds no values and ignores all method calls.
25
+ class NoopCache
26
+ # Swallows any number of parameters and returns nil.
27
+ def noop(*); end
28
+
29
+ alias_method :add, :noop
30
+ alias_method :add_many, :noop
31
+ alias_method :remove, :noop
32
+ alias_method :remove_many, :noop
33
+
34
+ def find(*)
35
+ []
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,76 @@
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 './logging'
24
+ require_relative './request_parameters'
25
+ require_relative './util'
26
+
27
+ require 'net/http'
28
+ require 'uri'
29
+
30
+ module ADAL
31
+ # A request that can be made to an authentication or token server.
32
+ class OAuthRequest
33
+ include RequestParameters
34
+ include Util
35
+
36
+ DEFAULT_CONTENT_TYPE = 'application/x-www-form-urlencoded'
37
+ DEFAULT_ENCODING = 'utf8'
38
+ SSL_SCHEME = 'https'
39
+
40
+ def initialize(endpoint, params)
41
+ @endpoint_uri = URI.parse(endpoint.to_s)
42
+ @params = params
43
+ end
44
+
45
+ def params
46
+ default_parameters.merge(@params)
47
+ end
48
+
49
+ ##
50
+ # Requests and waits for a token from the endpoint.
51
+ # @return TokenResponse
52
+ def execute
53
+ request = Net::HTTP::Post.new(@endpoint_uri.path)
54
+ add_headers(request)
55
+ request.body = URI.encode_www_form(string_hash(params))
56
+ TokenResponse.parse(http(@endpoint_uri).request(request).body)
57
+ end
58
+
59
+ private
60
+
61
+ ##
62
+ # Adds the necessary OAuth headers.
63
+ #
64
+ # @param Net::HTTPGenericRequest
65
+ def add_headers(request)
66
+ return if Logging.correlation_id.nil?
67
+ request.add_field(CLIENT_REQUEST_ID.to_s, Logging.correlation_id)
68
+ request.add_field(CLIENT_RETURN_CLIENT_REQUEST_ID.to_s, true)
69
+ end
70
+
71
+ def default_parameters
72
+ { encoding: DEFAULT_ENCODING,
73
+ AAD_API_VERSION => '1.0' }
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,48 @@
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
+ # Names of parameters in OAuth requests. This module can be included in any
25
+ # class to reference the parameters instead of referring to them as strings
26
+ # or symbols
27
+ module RequestParameters
28
+ AAD_API_VERSION = 'api-version'.to_sym
29
+ ASSERTION = 'assertion'.to_sym
30
+ CLIENT_ASSERTION = 'client_assertion'.to_sym
31
+ CLIENT_ASSERTION_TYPE = 'client_assertion_type'.to_sym
32
+ CLIENT_ID = 'client_id'.to_sym
33
+ CLIENT_REQUEST_ID = 'client-request-id'.to_sym
34
+ CLIENT_RETURN_CLIENT_REQUEST_ID = 'client-return-client-request-id'.to_sym
35
+ CLIENT_SECRET = 'client_secret'.to_sym
36
+ CODE = 'code'.to_sym
37
+ FORM_POST = 'form_post'.to_sym
38
+ GRANT_TYPE = 'grant_type'.to_sym
39
+ PASSWORD = 'password'.to_sym
40
+ REDIRECT_URI = 'redirect_uri'.to_sym
41
+ REFRESH_TOKEN = 'refresh_token'.to_sym
42
+ RESOURCE = 'resource'.to_sym
43
+ SCOPE = 'scope'.to_sym
44
+ UNIQUE_ID = 'unique_id'.to_sym
45
+ USER_INFO = 'user_info'.to_sym
46
+ USERNAME = 'username'.to_sym
47
+ end
48
+ end
@@ -0,0 +1,96 @@
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 './jwt_parameters'
24
+ require_relative './logging'
25
+
26
+ require 'jwt'
27
+ require 'openssl'
28
+ require 'securerandom'
29
+
30
+ module ADAL
31
+ # Converts client certificates into self signed JWTs.
32
+ class SelfSignedJwtFactory
33
+ include JwtParameters
34
+ include Logging
35
+
36
+ ##
37
+ # Constructs a new SelfSignedJwtFactory.
38
+ #
39
+ # @param String client_id
40
+ # The client id of the calling application.
41
+ # @param String token_endpoint
42
+ # The token endpoint that will accept the certificate.
43
+ def initialize(client_id, token_endpoint)
44
+ @client_id = client_id
45
+ @token_endpoint = token_endpoint
46
+ end
47
+
48
+ ##
49
+ # Creates a JWT from a client certificate and signs it with a private key.
50
+ #
51
+ # @param OpenSSL::X509::Certificate certificate
52
+ # The certifcate object to be converted to a JWT and signed for use
53
+ # in an authentication flow.
54
+ # @param OpenSSL::PKey::RSA private_key
55
+ # The private key used to sign the certificate.
56
+ # @return String
57
+ def create_and_sign_jwt(certificate, private_key)
58
+ JWT.encode(payload, private_key, RS256, header(certificate))
59
+ end
60
+
61
+ private
62
+
63
+ # The JWT header for a certificate to be encoded.
64
+ def header(certificate)
65
+ x5t = thumbprint(certificate)
66
+ logger.verbose("Creating self signed JWT header with thumbprint: #{x5t}.")
67
+ { TYPE => TYPE_JWT,
68
+ ALGORITHM => RS256,
69
+ THUMBPRINT => x5t }
70
+ end
71
+
72
+ # The JWT payload.
73
+ def payload
74
+ now = Time.now - 1
75
+ expires = now + 60 * SELF_SIGNED_JWT_LIFETIME
76
+ logger.verbose("Creating self signed JWT payload. Expires: #{expires}. " \
77
+ "NotBefore: #{now}.")
78
+ { AUDIENCE => @token_endpoint,
79
+ ISSUER => @client_id,
80
+ SUBJECT => @client_id,
81
+ NOT_BEFORE => now.to_i,
82
+ EXPIRES_ON => expires.to_i,
83
+ JWT_ID => SecureRandom.uuid }
84
+ end
85
+
86
+ ##
87
+ # Base 64 encoded thumbprint AKA fingerprint AKA SHA1 hash of the
88
+ # DER representation of the cert.
89
+ #
90
+ # @param OpenSSL::X509::Certificate certificate
91
+ # @return String
92
+ def thumbprint(certificate)
93
+ OpenSSL::Digest::SHA1.new(certificate.to_der).base64digest
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0"?>
2
+ <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
3
+ <s:Header>
4
+ <a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>
5
+ <a:messageID>urn:uuid:<%= message_id %></a:messageID>
6
+ <a:ReplyTo>
7
+ <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
8
+ </a:ReplyTo>
9
+ <a:To s:mustUnderstand="1"><%= @endpoint %></a:To>
10
+ <o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
11
+ <u:Timestamp u:Id="_0">
12
+ <u:Created><%= created.utc.iso8601 %></u:Created>
13
+ <u:Expires><%= expires.utc.iso8601 %></u:Expires>
14
+ </u:Timestamp>
15
+ <o:UsernameToken u:Id="ADALUsernameToken">
16
+ <o:Username><%= username.encode(xml: :text) %></o:Username>
17
+ <o:Password><%= password.encode(xml: :text) %></o:Password>
18
+ </o:UsernameToken>
19
+ </o:Security>
20
+ </s:Header>
21
+ <s:Body>
22
+ <trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
23
+ <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
24
+ <a:EndpointReference>
25
+ <a:Address><%= @applies_to %></a:Address>
26
+ </a:EndpointReference>
27
+ </wsp:AppliesTo>
28
+ <trust:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
29
+ <trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>
30
+ </trust:RequestSecurityToken>
31
+ </s:Body>
32
+ </s:Envelope>
33
+
34
+
35
+
@@ -0,0 +1,32 @@
1
+ <?xml version="1.0"?>
2
+ <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
3
+ <s:Header>
4
+ <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
5
+ <a:messageID>urn:uuid:<%= message_id %></a:messageID>
6
+ <a:ReplyTo>
7
+ <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
8
+ </a:ReplyTo>
9
+ <a:To s:mustUnderstand="1"><%= @endpoint %></a:To>
10
+ <o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
11
+ <u:Timestamp u:Id="_0">
12
+ <u:Created><%= created.utc.iso8601 %></u:Created>
13
+ <u:Expires><%= expires.utc.iso8601 %></u:Expires>
14
+ </u:Timestamp>
15
+ <o:UsernameToken u:Id="ADALUsernameToken">
16
+ <o:Username><%= username.encode(xml: :text) %></o:Username>
17
+ <o:Password><%= password.encode(xml: :text) %></o:Password>
18
+ </o:UsernameToken>
19
+ </o:Security>
20
+ </s:Header>
21
+ <s:Body>
22
+ <trust:RequestSecurityToken xmlns:trust="http://schemas.xmlsoap.org/ws/2005/02/trust">
23
+ <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
24
+ <a:EndpointReference>
25
+ <a:Address><%= @applies_to %></a:Address>
26
+ </a:EndpointReference>
27
+ </wsp:AppliesTo>
28
+ <trust:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</trust:KeyType>
29
+ <trust:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</trust:RequestType>
30
+ </trust:RequestSecurityToken>
31
+ </s:Body>
32
+ </s:Envelope>