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

Migration path for Spring SAML Extension users #8685

Closed
rajn opened this issue Jun 12, 2020 · 55 comments
Closed

Migration path for Spring SAML Extension users #8685

rajn opened this issue Jun 12, 2020 · 55 comments
Labels
in: saml2 An issue in SAML2 modules type: enhancement A general enhancement
Milestone

Comments

@rajn
Copy link

rajn commented Jun 12, 2020

Expected Behavior

We currently are using Spring SAML Extension 1.0.10 in SP mode. We integrate with different IDPs like OAM, OKTA, ADFS etc and it works smoothly.
Now, we need to upgrade as the underlying OpenSAML is quite old.
I see that Spring Security Core is the new place for SAML support and Spring SAML will not be available as a separate library.
It seems not all functionality from Spring SAML has been ported to Spring Security. We are specifically interested in SP Metadata generation and Single Logout. When will this be available in Spring Security SAML?
Is there a document that can be used for this migration path? ie From Spring SAML Extension to Spring Security SAML Feature set.

Current Behavior

Documentation for existing users of Spring SAML Extension is limited/ unable to find.

Context

@rajn rajn added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Jun 12, 2020
@jzheaux
Copy link
Contributor

jzheaux commented Jun 15, 2020

@rajn, thanks for reaching out about this. I think it makes sense to provide support for metadata generation as well as single logout.

Based on your feedback, I've added #8693 to track Spring Security's SP Metadata support.

Would you mind creating a ticket that indicates what you feel is needed to address your single logout use case?

As far as laying out a migration path, that's still a todo. I'll leave this ticket open for adding the appropriate documentation.

@jzheaux jzheaux added in: saml2 An issue in SAML2 modules and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 15, 2020
@jzheaux jzheaux added this to the 5.4.0-RC1 milestone Jun 15, 2020
@jeanblanchard
Copy link

I created #8731 for the "trigger a Single Logout" part, which is pretty important I think.

The other part would be receiving a Single Logout request from the IdP (i.e. the Single Logout was triggered from another SP), but I think it's less important (at least I for one have never used this)

@fpagliar
Copy link

@jzheaux is there a place for developers that are going through the migration to share common workarounds, supported / unsupported scenarios, etc? To aid in the meantime, until there's time for an official migration path.

@jzheaux
Copy link
Contributor

jzheaux commented Jun 29, 2020

@fpagliar, if it's a use case that you feel ought to be supported by Spring Security, then it's probably best to log a ticket about it. Then workarounds can be placed there. If there's an existing ticket, you can use that.

If it's a scenario that you don't feel should be supported by Spring Security, I'm not sure if there would be an official place inside Spring Security, but feel free to ping me on Gitter if you want help sorting through them.

@nlenoire
Copy link

Hello Spring Security Team,

I jump on this topic to add few more requirements.

We plan to use Spring Security to integrate with several IdPs using distincts protocols (OIDC, SAML2, LDAP, etc.).

By now, after some prototyping using Spring Security 5.3 with SAML2, we are facing several limitations due to some not yet supported features:

High Priority

Low Priority

  • Generate SP configuration from/driven by IDP Metadata document

  • Ability to configure Authentication Context Class Reference

Would it be possible to have ETA for those features?

Thanks

@jzheaux
Copy link
Contributor

jzheaux commented Jul 31, 2020

Thanks for sharing this list, @nlenoire.

I've got a question about one of them:

Support SAML response with unsigned assertions

I believe it's already possible to have a signed SAML response with unsigned assertions. Is this what you are looking for? I don't think we want to add first-class support for both the response and assertions being unsigned.

Otherwise, on the surface, several of the features sound reasonable, but I think I'd need more detail to know for sure. Would you be able to write up individual tickets for the features that you need, explaining each use case in greater detail?

@jgrandja jgrandja modified the milestones: 5.4.0-RC1, 5.4.0 Aug 5, 2020
@amergey
Copy link
Contributor

amergey commented Aug 10, 2020

I've got a question about one of them:

Support SAML response with unsigned assertions

This requirement comes from a customer that is using an IDP that does not sign encrypted assertions, would it be a valid requirement for spring-security to support unsigned encrypted assertions ?

@jzheaux
Copy link
Contributor

jzheaux commented Aug 13, 2020

@amergey, I don't think we want to support unsigned encrypted assertions. Can the provider sign the response as an alternative?

@nlenoire
Copy link

The customer will not accept any other alternative than its current configuration: Signed response, with encrypted unsigned assertions.

@jzheaux
Copy link
Contributor

jzheaux commented Aug 25, 2020

@nlenoire, that is a supported setup. So long as the response is signed, the assertions do not have to be signed.

@scho
Copy link

scho commented Nov 23, 2021

  • Ability to configure NameID Format
    Some IdPs requires specifying a NameID Format

I'm currently started to use the new SingleLogout feature from 5.6.0 and it looks like, my IDP requires specifying the NameID format.

Is there are a way to hack this feature into the OpenSamlLogoutRequestResolver or somewhere else until it's supported?
Or should I roll-out my on LogoutFilter?

Edit:
I figured out how to change the NameID Format:

// Set the parameters consumer
OpenSaml4LogoutRequestResolver resolver = new OpenSaml4LogoutRequestResolver(relyingPartyRegistrationResolver());
resolver.setParametersConsumer(saml2LogoutParameterConsumer());
// ...
// and set the resolver in the configure(HttpSecurity http) method:
http.saml2Logout(saml2Logout -> saml2Logout.logoutRequest(request -> request.logoutRequestResolver(openSaml4LogoutRequestResolver)))

@jzheaux
Copy link
Contributor

jzheaux commented Dec 13, 2021

@rajn
Copy link
Author

rajn commented Nov 25, 2022

looks like the answer is in your question :) why is Okta sending to /saml/sso it should send to saml2/sso right? please check the destination url in okta

@akhil-lm
Copy link

akhil-lm commented Nov 25, 2022

Hi @rajn, destination url is something my team can't change in Okta, since many clients of our application already have it set to '/saml/SSO' in their existing Okta configurations.

This is why I am using the SamlExtensionUrlForwardingFilter introduced in the spring sample to redirect/forward the '/saml/SSO' request to the correct url as per the new spring security saml2 support. Link to the sample :- https://github.com/spring-projects/spring-security-samples/tree/main/servlet/spring-boot/java/saml2/custom-urls

@marcusdacoregio
Copy link
Contributor

Another query I have is that by looking at the migration guide, I have come to a conclusion that I can implement the SSO using the new libraries with Java+Spring itself, and do not compulsorily need Spring boot.

That's right, in order to use Spring Security features it is not mandatory that you use Spring Boot, although it facilitates a lot of tasks.

When I enter my credentials, Okta calls the '/saml/SSO/' endpoint in my application. The problem I am facing right now is that for some reason, the status code for the POST call to '/saml/SSO/' is 403.

Given that the request is a POST, my first thought is that you are getting a CSRF error. Add logging.level.org.springframework.security=TRACE to your application.properties and check the console.
The SamlExtensionUrlForwardingFilter should run before the SecurityFilterChain to forward the request before any authorization happens.

@akhil-lm
Copy link

Thanks @marcusdacoregio, I appreciate your help so much.

@akhil-lm
Copy link

Hi @marcusdacoregio,
With some debugging of the spring filters, I could see the following problem :-
Invalid CSRF token found for https://mycompany.abc.com/company/saml/SSO/

Basically in the CsrfFilter of Spring security, there's this code that's returning me the actualToken value as null :-

String actualToken = request.getHeader(csrfToken.getHeaderName());
if (actualToken == null) {
	actualToken = request.getParameter(csrfToken.getParameterName());
}

So it seems as if the request doesn't have the X-CSRF-TOKEN set as one of the headers. Could you please provide some inputs on how to tackle this problem?

@akhil-lm
Copy link

Hi @marcusdacoregio,
To resolve the above issue, I disabled csrf :-
http.csrf().disable()

That did resolve the 403 error, but now what's happening is that I am getting recursive calls to '/saml2/authenticate/{registrationId}', '/saml/SSO' and the IdP (Okta) url

Basically I am getting recursive redirections to these three endpoints in a loop, and my request is finally ending up in 429 Too Many Requests for the IdP url. Request your inputs on the same.

@akhil-lm
Copy link

Hi @marcusdacoregio,
I can see that my request is ending up in 'AccessDeniedException' based on a check in the AuthorizationFilter (of Spring) :-
AuthorizationDecision decision = this.authorizationManager.check(this::getAuthentication, request);

In the check method, there's the following code :-

private boolean isGranted(Authentication authentication) {
    return authentication != null && isNotAnonymous(authentication) && authentication.isAuthenticated();
}

Here, the condition 'isNotAnonymous(authentication)' is returning false for me. Could this be the reason behind the infinite loop redirects that I am seeing?

@akhil-lm
Copy link

akhil-lm commented Nov 27, 2022

SecurityContextHolder.getContext().getAuthentication()
This returns null, resulting in the creation of the AnonymousAuthenticationToken object. I am wondering if it's related to the infinite redirects.

@marcusdacoregio
Copy link
Contributor

Hi @akhil-lm ,

the ideal scenario would be to not disable CSRF protection.
Did you register the FilterChainProxy for FORWARD requests?

If you are not using Spring Boot you might need to use:

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    @Override
    protected EnumSet<DispatcherType> getSecurityDispatcherTypes() {
        return EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.FORWARD,
                DispatcherType.FORWARD, DispatcherType.INCLUDE);
    }

}

@akhil-lm
Copy link

Thanks @marcusdacoregio, this worked. I've removed the code to disable csrf.

@akhil-lm
Copy link

Hi @marcusdacoregio,
I'm currently facing the following errors in my OpenSamlAuthenticationProvider.java :-

[[invalid_signature] Invalid signature for object [id81831180107548381835751282]

[invalid_destination] Invalid destination [https://xyz.companyname.com/company/login/saml2/sso/lm] for SAML response [id81831180107548381835751282]

[invalid_issuer] Invalid issuer [http://www.okta.com/exk3dmunf4rkOEynb123] for SAML response [id81831180107548381835751282]

[invalid_signature] Invalid assertion [id8183118010910692226156343] for SAML response [id81831180107548381835751282]: Signature of Assertion 'id8183118010910692226156343' from Issuer 'http://www.okta.com/exk3dmunf4rkOEynb123' was not valid

[invalid_assertion] Invalid assertion [id8183118010910692226156343] for SAML response [id81831180107548381835751282]: Condition '{urn:oasis:names:tc:SAML:2.0:assertion}AudienceRestriction' of type 'null' in assertion 'id8183118010910692226156343' was not valid.: None of the audiences within Assertion 'id8183118010910692226156343' matched the list of valid audiances]

Is there any single piece of configuration I might be missing out on that might be resulting in all the above errors? Or each of them may be due to individual reasons? Request your inputs on the same.

@marcusdacoregio
Copy link
Contributor

Hi @akhil-lm,

I'm afraid I cannot help now, it seems that it is a configuration issue on your side. I recommend debugging the OpenSaml4AuthenticationProvider in order to figure out the current x expected values.

@akhil-lm
Copy link

Hi @marcusdacoregio,
No problem. Yes, I will do that, and will seek your help if I have specific queries. Thanks.

@akhil-lm
Copy link

Hi @marcusdacoregio,
I found success in getting the login to work. But I had to set my Single sign on URL in Okta to '/login/sam2/sso/{registrationId}'.

When I set it to '/saml/SSO', I get the '403 Forbidden' error. On debugging, I found that in the following code, the requiresAuthenticationRequestMatcher is referring to '/login/sam2/sso/{registrationId}' and the HttpServletRequest object refers to '/saml/SSO'. Hence, the requiresAuthentication() always returns false, and the attemptAuthentication() method doesn't get called.

protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
if (this.requiresAuthenticationRequestMatcher.matches(request)) {
	return true;
}
if (this.logger.isTraceEnabled()) {
	this.logger
			.trace(LogMessage.format("Did not match request to %s", this.requiresAuthenticationRequestMatcher));
}
return false;
}

Could you please provide your input on this? I feel that I may not have the proper configuration for SamlExtensionUrlForwardingFilter, that's probably resulting in HttpServletRequest request object still referring to '/saml/SSO'.

@akhil-lm
Copy link

I confirmed that SamlExtensionUrlForwardingFilter with the following configuration is seemingly being ignored by Spring :-

@Component
@Order(-101) // To run before FilterChainProxy
public class SamlExtensionUrlForwardingFilter extends OncePerRequestFilter {

My Filter chain proxy configuration is as follows :-

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Value("classpath:credentials/rp-private.key")
    RSAPrivateKey privateKey;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(
                relyingPartyRegistrations());
        http
                .authorizeHttpRequests((authorize) -> authorize
                        .anyRequest().authenticated()
                )
                .saml2Login()
                    .successHandler(new MyAuthenticationSuccessHandler());
        return http.build();
    }

Do I need to register the SamlExtensionUrlForwardingFilter somewhere else as well?

@marcusdacoregio
Copy link
Contributor

Hi @akhil-lm, did you follow all the steps from the sample's README?

You have to change your RelyingPartyRegistration to the old URLs, is this already done?

singlelogout:
              binding: POST
              url: "{baseUrl}/saml/logout" (2)
              responseUrl: "{baseUrl}/saml/SingleLogout" (3)
            acs:
              location: "{baseUrl}/saml/SSO" (4)

@akhil-lm
Copy link

Hi @marcusdacoregio,
I had some misconfigurations, but I corrected them and now it's working for me.

But I had to register my SamlExtensionUrlForwardingFilter like this :-

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
      RelyingPartyRegistrationResolver relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(
              relyingPartyRegistrations());
      http
              .addFilterBefore(new SamlExtensionUrlForwardingFilter(), DisableEncodeUrlFilter.class)

The filter was not being picked before the filterChain by just defining it with order -101.

@marcusdacoregio
Copy link
Contributor

marcusdacoregio commented Nov 30, 2022

Hi @akhil-lm,

That's my bad, I forgot that you were not using Spring Boot and that it's Spring Boot that picks Filter beans automatically. In your case, you really have to register the Filter in the SecurityFilterChain or in your regular filter chain manually.

@akhil-lm
Copy link

No problem @marcusdacoregio,
so the way I am registering it is correct?

@marcusdacoregio
Copy link
Contributor

Yes, @akhil-lm.

I feel that further inquiries about the migration path from Spring SAML Extension should be discussed in individual issues (and maybe linked here), this issue is becoming confusing with all those comments.

Please, if you have more questions let's discuss them in a separate ticket or Stackoverflow question and improve our migration path.

@akhil-lm
Copy link

Sure @marcusdacoregio, noted. Thank you.

@jzheaux
Copy link
Contributor

jzheaux commented Dec 20, 2022

@siddharth-78
Copy link

siddharth-78 commented Aug 16, 2023

I'm currently using spring-security-saml2-core [1.0.10.RELEASE], and I'm looking to upgrade it to spring-security-saml2-core [2.0.0.M31] instead of the spring-security-library, since a lot of code change will be required while switching libraries.

During the process of switch from 1.0.10.RELEASE -> 2.0.0.M31, a lot of packages are missing, requesting you to point to the alternative packages in place
[PS. I don't see any comprehensive migration document, which points these things out for e.g. this documentation of restsharp is clearly states the alternatives restsharp.dev/v107 ]

Missing imports:

  • org.opensaml.saml2.*;
  • org.opensaml.xml.*;
  • import org.springframework.security.saml.key.JKSKeyManager; [JKSKeyManager is missing]
  • import org.springframework.security.saml.metadata.*;

@siddharth-78
Copy link

siddharth-78 commented Aug 18, 2023

Hey guys any leads?

I'm working on upgrading spring-security-saml2-core from version 1.0.10.RELEASE to 2.0.0.M31 in my project. I don't want to switch to the newer spring-security-library. After the upgrade, I face the following missing import errors on compilation:

  • org.opensaml.saml2.metadata (from org.opensaml:opensaml:2.6.6 jar)

  • org.opensaml.xml (from org.opensaml:xmltooling:1.4.4 jar)

  • org.opensaml.xml.security (from org.opensaml:xmltooling:1.4.4 jar)

  • org.opensaml.xml.signature (from org.opensaml:xmltooling:1.4.4 jar)

  • org.springframework.security.saml.key (from org.springframework.security.extensions:spring-security-saml2-core:1.0.10.RELEASE jar)

  • org.springframework.security.saml.metadata (from org.springframework.security.extensions:spring-security-saml2-core:1.0.10.RELEASE jar)

  • org.opensaml.xml.security.credential (from org.opensaml:xmltooling:1.4.4 jar)

  • org.springframework.security.providers (from org.springframework.security.extensions:spring-security-saml2-core:1.0.10.RELEASE jar)

  • org.opensaml.saml2.core (from org.opensaml:opensaml:2.6.6 jar)

  • org.springframework.security.saml.userdetails (from org.springframework.security.extensions:spring-security-saml2-core:1.0.10.RELEASE jar)

These missing imports are crucial for my application, and I'm unable to compile the code without resolving them.

I was expecting the migration to be straightforward, but unfortunately, that was not the case. I've looked for migration documentation to help with the transition, but the only document available is the SAML 2.0 Migration Guide. However, it's poorly written and doesn't suggest alternate packages for the ones that have changed.

I expected to find a clear and concise migration path, including the necessary package replacements. Now, I'm stuck with these compilation errors and unsure how to proceed.

Can anyone point me to the alternatives or solutions for these missing imports? Any help or guidance on this migration would be greatly appreciated.

@marcusdacoregio
@jzheaux

@martinwunderlich-celonis

@siddharth-78 Have you had any luck with the migration from Spring SAML extension to Spring Security? Any resources you would recommend in addition to the migration guide mentioned?

@siddharth-78
Copy link

@martinwunderlich-celonis None yet, here's something that might help you
#13663

@OrangeDog
Copy link
Contributor

For the record, here is what the OpenSAML has to say about the sort of design that Spring Security has moved to:

It is very dangerous to attempt to use parts of the library in isolation without making use of all of its relevant components. In particular, implementing your own XML processing code, using XML parsing classes other than the ParserPool components provided by the library, using your own security processing code, omitting proper support for SAML metadata, etc. are all risky choices that may lead to security flaws and incomplete, unsafe, and ill-advised SAML solutions. The Shibboleth Project discourages such approaches in the strongest possible terms. Use all of it that applies to the task at hand, or use none of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: saml2 An issue in SAML2 modules type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests