kbeckman / omniauth-wsfed Goto Github PK
View Code? Open in Web Editor NEWWS-Federation and WS-Trust strategy for OmniAuth.
License: Other
WS-Federation and WS-Trust strategy for OmniAuth.
License: Other
Using an ADFS server, the server is sending callback with an SAMLresponse parameter.
But the callback is failing as no params['wresult'] is included
Could the tool decrypt the SAMLresponse ?
I am thinking can the SAMLresponse at the moment not handled in this gem, be decrypted? i.e adding saml into it.
Lately, we've seen a lot of failures with Azure ACS in various test and PROD environments where WSFed token validation (omniauth callback) has failed because of the Created_At validation (validating the token was not issued in the "future"). There were observed discrepancies of as much as 10 seconds between the Created_At attribute of AuthN tokens and the DateTime.now.utc value on our web servers. This was only observed in scenarios using Azure ACS as a federation provider, but I'm assuming that it has or will happen in other scenarios / environments as well.
To resolve the issue, I'm going to remove the Created_At validation entirely (AuthCallbackValidator) as this was a fairly aggressive validation that doesn't make a lot of sense in environments where server times are not synchronized.
If anyone has any additional feedback on this issue, I would appreciate it.
Setup: ADFS 3.0
SAML: 2.0
NoMethodError (undefined method `text' for nil:NilClass):
omniauth-wsfed (0.3.3.pre.beta) lib/omniauth/strategies/wsfed/saml_2_token.rb:23:in `issuer'
omniauth-wsfed (0.3.3.pre.beta) lib/omniauth/strategies/wsfed/auth_callback.rb:50:in `issuer'
omniauth-wsfed (0.3.3.pre.beta) lib/omniauth/strategies/wsfed/auth_callback_validator.rb:32:in `validate_issuer!'
omniauth-wsfed (0.3.3.pre.beta) lib/omniauth/strategies/wsfed/auth_callback_validator.rb:21:in `validate!'
omniauth-wsfed (0.3.3.pre.beta) lib/omniauth/strategies/wsfed.rb:41:in `callback_phase'
omniauth (1.3.1) lib/omniauth/strategy.rb:227:in `callback_call'
omniauth (1.3.1) lib/omniauth/strategy.rb:184:in `call!'
omniauth (1.3.1) lib/omniauth/strategy.rb:164:in `call'
omniauth (1.3.1) lib/omniauth/builder.rb:63:in `call'
Content of "document":
<t:RequestSecurityTokenResponse xmlns:t='http://schemas.xmlsoap.org/ws/2005/02/trust'><t:Lifetime><wsu:Created xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>2016-01-11T20:33:42.797Z</wsu:Created><wsu:Expires xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>2016-01-11T21:33:42.797Z</wsu:Expires></t:Lifetime><wsp:AppliesTo xmlns:wsp='http://schemas.xmlsoap.org/ws/2004/09/policy'><wsa:EndpointReference xmlns:wsa='http://www.w3.org/2005/08/addressing'><wsa:Address>https://projectctrl.myurl.com/</wsa:Address></wsa:EndpointReference></wsp:AppliesTo><t:RequestedSecurityToken><saml:Assertion AssertionID='_2b6b8086-4373-4013-a48b-0532501fb68f' IssueInstant='2016-01-11T20:33:42.797Z' Issuer='http://logon.myurl.com/adfs/services/trust' MajorVersion='1' MinorVersion='1' xmlns:saml='urn:oasis:names:tc:SAML:1.0:assertion'><saml:Conditions NotBefore='2016-01-11T20:33:42.797Z' NotOnOrAfter='2016-01-11T21:33:42.797Z'><saml:AudienceRestrictionCondition><saml:Audience>https://projectctrl.myurl.com/</saml:Audience></saml:AudienceRestrictionCondition></saml:Conditions><saml:AttributeStatement><saml:Subject><saml:SubjectConfirmation><saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod></saml:SubjectConfirmation></saml:Subject><saml:Attribute AttributeName='emailaddress' AttributeNamespace='http://schemas.xmlsoap.org/ws/2005/05/identity/claims'><saml:AttributeValue>[email protected]</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName='givenname' AttributeNamespace='http://schemas.xmlsoap.org/ws/2005/05/identity/claims'><saml:AttributeValue>Max</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName='surname' AttributeNamespace='http://schemas.xmlsoap.org/ws/2005/05/identity/claims'><saml:AttributeValue>Mustermann</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AuthenticationStatement AuthenticationInstant='2016-01-11T15:03:46.092Z' AuthenticationMethod='urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'><saml:Subject><saml:SubjectConfirmation><saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod></saml:SubjectConfirmation></saml:Subject></saml:AuthenticationStatement><ds:Signature xmlns:ds='http://www.w3.org/2000/09/xmldsig#'><ds:SignedInfo><ds:CanonicalizationMethod Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'/><ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/><ds:Reference URI='#_2b6b8086-4373-4013-a48b-0532501fb68f'><ds:Transforms><ds:Transform Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature'/><ds:Transform Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'/></ds:Transforms><ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'/><ds:DigestValue>mKcHkXOnOY9zCse42Vl8+ymsTZL82SctlREp8MhUS2o=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>RfN7wW//IF3MvDv+5okhnaAjrRRObZe27TjT+3J2pP3YcQjX8VJ6pKVoDv8+V3et901iU6GIeLTjq7obXJoQP4hdpEDohhqEw1CLDZGLZ93mUUS+k9WWnK9NsCUyrFeG43reJHj3B7Pu7ke1LdpHDk2kFrFX0ZYZ2gKJM+bXygn8QuMO+EoLAM3VvXydFg4nbBOIGwA8cmTsB/cg7bjAHqkaAbK4gUldtzfKhtlNriUJHTNNPTgSe6e/JI37my+B9vg0ReS02Y7tlVKQLBrkwNJr3JlFxI80/Y2iUGKI6wHi3jjgeuLj3l3d1oW/LANDqQXtGMS253r7woRJiH9vWw==</ds:SignatureValue><KeyInfo xmlns='http://www.w3.org/2000/09/xmldsig#'><X509Data><X509Certificate>MIIC6DCCAdCgAwIBAgIQE2ZrrwJtJ5lAZPJDuYsjyTANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVBREZTIFNpZ25pbmcgLSBsb2dvbi5iZWFyaW5ncG9pbnQuY29tMB4XDTE1MDQyODAzMjAzM1oXDTE3MDQyNzAzMjAzM1owMDEuMCwGA1UEAxMlQURGUyBTaWduaW5nIC0gbG9nb24uYmVhcmluZ3BvaW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALR6YvbB03eQjO6JYhrFdS1rsQq9ewM27rVgaNDu9gTt5MsYnb7aabQKExhN5+UQFMAw3kKkyXeGktWZ6KMTH23Efb5FHjIVWDLCLBT/gq+58Z475PfXGtOV4CgMP0OrHqcM1mYyykuZem454zgotnLmGOSi+FTApNA5vOJLXiuUm9njKUbWF3DmQV3RJR3xqgtMAbhvI8rBiD8Rs08JuzELjW5gMlYpRuz6HDDsAqNZXo/oll2cHPsJvtN41zw44MVP8hVN1kbJs487cKu9AiJfSx+5PoFnzIY29emwK1KVt0ZLRVoTa7KVgTK8KTLCA0GHsGsy0iozt6s6PPa9teMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAnyrFiciczAQOs4loHxR1z1bImSeAZhEipiqTSY8PD48O+ljkblxU6gvZToaR7cgaC6tMVFcUEkg94xGvb6nu+1VrdhUPiD7XKW31EC541NpR8DCssmrwtfe8cqqAiPV+SD65yIf7ThnGHvomNX6depDRUgDyF4oZQciCDXQkoScU+TgUKNiguAy6mCnUg6xsnuDMxhdpQytR2551W2fe4o62npsPr1Ct/j4pEk/s9XLCCYZ0trDbmHngQKVGEx4eahp1Tf8QARHyhPEsfHI0PixXaofNPwetTjRm5dQt7lK5pcG12cTXI+/wSvxYOK7OhnXDFxSG5XleNjFAjw3cAQ==</X509Certificate></X509Data></KeyInfo></ds:Signature></saml:Assertion></t:RequestedSecurityToken><t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType><t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType><t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType></t:RequestSecurityTokenResponse>
Using ADFS3 as the IDP, the signature and digests fails validation by mismatched hashes.
Not sure if there is a configuration issue on my end, but from what I can see the problem is due to carriage returns, tabs and whitespace being left in the canonicalized string.
Would be great to see this fixed if indeed it is a problem (not sure if you support ADFS3.0), the fix I implemented merely stripped out undesired excess characters which caused the digests to mismatch, have no tested against other IdP's.
Original:
canon_hashed_element = canoner.canonicalize(hashed_element)
...
canon_string = canoner.canonicalize(signed_info_element)
Fix:
canon_hashed_element = canoner.canonicalize(hashed_element).gsub(/\n\t/, " ").gsub(/>\s*</, "><")
...
canon_string = canoner.canonicalize(signed_info_element).gsub(/\n\t/, " ").gsub(/>\s*</, "><")
NoMethodError (undefined method `text' for nil:NilClass):
vendor/bundle/ruby/2.2.0/gems/omniauth-wsfed-0.3.3.pre.beta/lib/omniauth/strategies/wsfed/saml_2_token.rb:18:in `issuer'
vendor/bundle/ruby/2.2.0/gems/omniauth-wsfed-0.3.3.pre.beta/lib/omniauth/strategies/wsfed/auth_callback.rb:50:in `issuer'
vendor/bundle/ruby/2.2.0/gems/omniauth-wsfed-0.3.3.pre.beta/lib/omniauth/strategies/wsfed/auth_callback_validator.rb:32:in `validate_issuer!'
vendor/bundle/ruby/2.2.0/gems/omniauth-wsfed-0.3.3.pre.beta/lib/omniauth/strategies/wsfed/auth_callback_validator.rb:21:in `validate!'
vendor/bundle/ruby/2.2.0/gems/omniauth-wsfed-0.3.3.pre.beta/lib/omniauth/strategies/wsfed.rb:41:in `callback_phase'
As of right now, this gem will not decrypt encrypted SAML tokens -- it only validates unencrypted, signed tokens.. This isn't really a problem as long as tokens are posted over SSL, but the extra security of supporting encrypted tokens is required for complete protocol support
There may be instances where relying parties need to support multiple issuers (rather than a single issuer or single Federation Provider). Add the functionality to support multiple issuers in the YML configuration and add the necessary callback validation to use a list of issuers.
Currently, this gem only supports the SAML 2.0 AuthN token format. Add support for SAML 1.1 format tokens.
The back story can be found here.
The omniauth dependency needs to be bumped to version 1.2 along with any other outdated gems...
RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.
via e.g.
spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']
Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can image, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.
There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.
I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!
Appendix:
If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies
p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post aobut this project for more information.
For some reason Azure auth_callback.audience
returns the URL with a trailing slash ignoring the fact that the app doesn't have it on Azure config.
tl;dr: this will fail:
auth_callback.audience == wsfed_settings[:realm]
my fix: just add a slash both in the omni config and on the Azure dashboard.
This small issue really burned lots of my time / nicely done Azure ๐
I've found this issue in a production environment... When the 'wresult' parameter is null or empty, an exception is raised in xml_secuirty.rb because there's no XML to parse... This occurs when an end user actually issues a HTTP GET request for /auth/wsfed/callback rather than properly POSTing a valid AuthN token. It would also occur when an empty/nil AuthN token is posted (by an IdP or federation provider) to the wsfed callback endpoint.
[GEM_ROOT]/gems/omniauth-wsfed-0.2.1/lib/omniauth/strategies/wsfed/xml_security.rb:51:in validate
;
[GEM_ROOT]/gems/omniauth-wsfed-0.2.1/lib/omniauth/strategies/wsfed.rb:37:in callback_phase
;
[GEM_ROOT]/gems/omniauth-1.1.4/lib/omniauth/strategy.rb:226:in callback_call
;
[GEM_ROOT]/gems/omniauth-1.1.4/lib/omniauth/strategy.rb:182:in call!
;
[GEM_ROOT]/gems/omniauth-1.1.4/lib/omniauth/strategy.rb:164:in call
;
[GEM_ROOT]/gems/request_store-1.0.5/lib/request_store/middleware.rb:9:in call
;
[GEM_ROOT]/gems/warden-1.2.1/lib/warden/manager.rb:35:in block in call
;
[GEM_ROOT]/gems/warden-1.2.1/lib/warden/manager.rb:34:in catch
;
[GEM_ROOT]/gems/warden-1.2.1/lib/warden/manager.rb:34:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/best_standards_support.rb:17:in call
;
[GEM_ROOT]/gems/rack-1.4.5/lib/rack/etag.rb:23:in call
;
[GEM_ROOT]/gems/rack-1.4.5/lib/rack/conditionalget.rb:25:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/head.rb:14:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/params_parser.rb:21:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/flash.rb:242:in call
;
[GEM_ROOT]/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:210:in context
;
[GEM_ROOT]/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:205:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/cookies.rb:341:in call
;
[GEM_ROOT]/gems/activerecord-3.2.12/lib/active_record/query_cache.rb:64:in call
;
[GEM_ROOT]/gems/activerecord-3.2.12/lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/callbacks.rb:28:in block in call&
;
[GEM_ROOT]/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:405:in _run__3846457059957216958__call__1193386541527023715__callbacks
;
[GEM_ROOT]/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:405:in __run_callback
;
[GEM_ROOT]/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:385:in _run_call_callbacks
;
[GEM_ROOT]/gems/activesupport-3.2.12/lib/active_support/callbacks.rb:81:in run_callbacks
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/callbacks.rb:27:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/remote_ip.rb:31:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/debug_exceptions.rb:16:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/show_exceptions.rb:56:in call
;
[GEM_ROOT]/gems/railties-3.2.12/lib/rails/rack/logger.rb:32:in call_app
;
[GEM_ROOT]/gems/railties-3.2.12/lib/rails/rack/logger.rb:16:in block in call
;
[GEM_ROOT]/gems/activesupport-3.2.12/lib/active_support/tagged_logging.rb:22:in tagged
;
[GEM_ROOT]/gems/railties-3.2.12/lib/rails/rack/logger.rb:16:in call
;
[GEM_ROOT]/gems/actionpack-3.2.12/lib/action_dispatch/middleware/request_id.rb:22:in call
;
[GEM_ROOT]/gems/rack-1.4.5/lib/rack/methodoverride.rb:21:in call
;
[GEM_ROOT]/gems/rack-1.4.5/lib/rack/runtime.rb:17:in call
;
[GEM_ROOT]/gems/activesupport-3.2.12/lib/active_support/cache/strategy/local_cache.rb:72:in call
;
[GEM_ROOT]/gems/rack-1.4.5/lib/rack/lock.rb:15:in call
;
[GEM_ROOT]/gems/rack-cache-1.2/lib/rack/cache/context.rb:136:in forward
;
[GEM_ROOT]/gems/rack-cache-1.2/lib/rack/cache/context.rb:245:in fetch
;
[GEM_ROOT]/gems/rack-cache-1.2/lib/rack/cache/context.rb:185:in lookup
;
[GEM_ROOT]/gems/rack-cache-1.2/lib/rack/cache/context.rb:66:in call!
;
[GEM_ROOT]/gems/rack-cache-1.2/lib/rack/cache/context.rb:51:in call
;
[GEM_ROOT]/gems/rack-mini-profiler-0.1.23/Ruby/lib/mini_profiler/profiler.rb:209:in call
;
[GEM_ROOT]/gems/railties-3.2.12/lib/rails/engine.rb:479:in call
;
[GEM_ROOT]/gems/railties-3.2.12/lib/rails/application.rb:223:in call
;
[GEM_ROOT]/gems/railties-3.2.12/lib/rails/railtie/configurable.rb:30:in method_missing
;
When token decryption is added, the gem/ YAML config will have to include X509 cert details for decryption. I'm going to rename the existing certificate settings to reflect the fact that they're actually used for signature validation and add new settings for decryption certificates.
I get this error when I get the response back from the ACS:
app error: undefined method `text' for nil:NilClass (NoMethodError)
/app/vendor/bundle/ruby/2.2.0/gems/omniauth-wsfed-0.2.3/lib/omniauth/strategies/wsfed/auth_callback.rb:40:in `audience'
The parsing fails because in the response I am getting there is a wsa
namespace applied to the EndpointReference
and Address
nodes:
<wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Address>...</wsa:Address>
</wsa:EndpointReference>
I am using a WS-Federation identity provider connected to Azure AD. This is just a development setup so I can run my own AD. Oddly, I have a live setup (not managed by me) that sends almost the exact same response but without the wsa
namespace on that one section of XML. I've verified that they're both using SAML 2.0 tokens, and in fact everything else about the response structure is exactly the same.
So I'm curious if it's possible that something about my configuration is causing the wsa
namespace to be applied, or perhaps different setups cause slightly different responses (in which case I assume a patch to support either with-or-without the namespace would be appropriate?).
I am using version 0.2.3 of the gem but I did check the development and beta branches to see if this had already been addressed. Adding the wsa
namespace fixes the issue for my development AD and the request completes.
I also noticed that the SAML 1.0 token handler explicitly does use the wsa
namespace when finding the audience.
I'm new to Azure/WSFed so if there is any other information I can provide please let me know.
I'm using AD-FS directly without an Azure ACS namespace. I mentioned that the AD-FS server does not reply an issued token with the ds-namespace when I remove this in the XMLSecurity method, the systems works. Do I something wrong or is this gem more focused on ACS?
REXML::XPath.each(sig_element, "//--->ds:<---Reference") do |ref|
uri = ref.attributes.get_attribute("URI").value
hashed_element = REXML::XPath.first(self, "//[@-->AssertionID<--='#{uri[1,uri.size]}']")
Currently I can't find a sample configuration for ADFS2.0 similar to the existing sample for Windows Azure ACS namespace.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.