Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiSamlStrategy and InResponseTo are Incompatible by Default #334

Closed
gluxon opened this issue Jan 6, 2019 · 10 comments
Closed

MultiSamlStrategy and InResponseTo are Incompatible by Default #334

gluxon opened this issue Jan 6, 2019 · 10 comments

Comments

@gluxon
Copy link

gluxon commented Jan 6, 2019

For every HTTP request, MultiSamlStrategy creates a brand new SAML object. This in turn creates a new InMemoryCacheProvider.

Meaning by default, the InResponseTo setting will always cause the middleware to fail with "InResponseTo is not valid". Cache keys will never persist beyond the life time of a single HTTP request unless a custom cacheProvider is supplied.

I don't think the usage of two officially supported parts of the library should silently break. There are a 2 ways to fix this (that I see):

  1. Add an error if a custom cacheProvider isn't supplied by the user when using the MultiSamlStrategy. Forcing users to reconfigure this library with an external cache store would workaround this issue.
  2. Have MultiSamlStrategy hold onto its ownInMemoryCacheProvider objects by default that it passes to new SAML instances. To do this securely, it would need to persist caches for each identity provider.

I lean towards 2, but unfortunately the current API design doesn't require each identity provider to be uniquely keyed. The endpoint SAML option gets close, but that can change with binding methods.

Edit: To be clear, I'm just hoping to open a discussion on how to best resolve this. I'm not demanding it to be fixed or trying to force a solution. I may be able to submit a pull request once we agree on something.

@gluxon
Copy link
Author

gluxon commented Jan 6, 2019

Actually, I forgot that the optional idpIssuer parameter existed. That would satisfy the requirement for uniquely identifying IdPs.

@stavros-wb
Copy link
Contributor

@gluxon nice issue description. Would it be a problem to implement 2 without partitioning the cache per provider?

@gluxon
Copy link
Author

gluxon commented Jan 7, 2019

I'm not sure how big of a problem it would be in practice, but it would allow a malicious identity provider to respond to an authentication request made to a different identity provider (assuming SAML response signing is off). If response signing is enforced, then not partitioning the cache should be fine.

@stavros-wb I just realized that you wrote MultiSamlStrategy. Thanks for that! It's been very useful to me.

@stavros-wb
Copy link
Contributor

another option would be to hash the provider's data. given that the values don't change, it could be a poor man's id @markstos wdyt?

stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
stavros-wb added a commit to stavros-wb/passport-saml that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

node-saml#334
markstos pushed a commit that referenced this issue Feb 8, 2019
Either use cache provided by user, or a default memory
cache to store InResponse parameters. This cache is not
yet partitioned per provider, which means a malicious
provider could do replay attacks by using anothers
unconsummed `InResponse` values

#334
@stavros-wb
Copy link
Contributor

@gluxon can you try with the latest master?

@gluxon
Copy link
Author

gluxon commented Apr 18, 2019

@stavros-wb Sorry for the late response, but this works! Thank you!

@gluxon gluxon closed this as completed Apr 18, 2019
@crossan007
Copy link

crossan007 commented Nov 16, 2021

It seems like 3.2.0 no longer defaults to InMemoryCacheProvider for MultiSamlStrategy (possibly as of 224f25f).

Any ideas if this was an intentional change?

I am still able to explicitly define a InMemoryCacheProvider in my initialization options as cacheProvider

i.e.

import { CacheProvider } from "passport-saml/lib/node-saml/inmemory-cache-provider";

...
const SAMLCacheProvider = new CacheProvider({
  keyExpirationPeriodMs: 5000
});
...

passport.use(new MultiSamlStrategy({
  getSamlOptions: getSamlOptions,
  maxAssertionAgeMs: 5000,
  acceptedClockSkewMs: 5000,
  validateInResponseTo: true,
  wantAssertionsSigned: true,
  audience: appVars.saml.SPEntityId,
  signatureAlgorithm: "sha256",
  digestAlgorithm: "sha256",
  cacheProvider: SAMLCacheProvider
},
...

@cjbarth
Copy link
Collaborator

cjbarth commented Nov 17, 2021

What is the last version that worked as you expected @crossan007 ?

@crossan007
Copy link

I'm not actually sure.

I'm working on a new project and attempting to use the library.

I was searching through issues when I found the addition of the default cache provider for multi saml, and then dug through the commit history to locate where the default cache provider was removed when I realized what was added doesn't seem to work

@cjbarth
Copy link
Collaborator

cjbarth commented Nov 17, 2021

If my memory serves me correctly, this was removed because we want consumers to be explicit about which cache provider they use. Feel free to specify an InMemoryCacheProvider yourself during construction. I see that this change was made for the 3.0.0 release. It is possible that some documentation is out of date. Please feel free to create a PR to fix any documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants