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

Refactored out Servlet dependencies from core and toolkit #395

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

markkolich
Copy link

@markkolich markkolich commented Mar 5, 2023

Another proposed solution for #349 and #115.

  • Introduced servlet-jakarta and servlet-javax which provide differing implementations of the core HttpRequest and HttpResponse interfaces depending on the servlet container implementation where the library is consumed
  • Teased apart HTTP request and HTTP response objects along a common seam and refactored all core and toolkit code
  • Removed all dependencies on the servlet API from core and toolkit
  • Bumped version to 3.0.0

With this change, if you're on a container pre-EE9, then you declare a dependency on:

<dependency>
  <groupId>com.onelogin</groupId>
  <artifactId>java-saml</artifactId>
  <version>3.0.0</version>
</dependency>
<dependency>
  <groupId>com.onelogin</groupId>
  <artifactId>java-saml-servlet-javax</artifactId>
  <version>3.0.0</version>
</dependency>

If you're on an EE9 or later container, then you declare a dependency on:

<dependency>
  <groupId>com.onelogin</groupId>
  <artifactId>java-saml</artifactId>
  <version>3.0.0</version>
</dependency>
<dependency>
  <groupId>com.onelogin</groupId>
  <artifactId>java-saml-servlet-jakarta</artifactId>
  <version>3.0.0</version>
</dependency>

Of course, this PR also opens the door to non-servlet container implementations, meaning someone in Akka, Play, etc. could use this library as well as long as they provide their own HttpRequest and HttpResponse implementation. The servlet API dependency in core and toolkit has been completely removed.

Usage on pre-EE9 containers look like this:

import com.onelogin.saml2.servlet.javax.JavaxSamlHttpRequest;
import com.onelogin.saml2.servlet.javax.JavaxSamlHttpResponse;

final HttpRequest request = JavaxSamlHttpRequest.makeHttpRequest(javaxServletRequest);
final HttpResponse response = JavaxSamlHttpResponse.makeHttpResponse(javaxServletResponse);

final Auth auth = new Auth(saml2Settings, request, response);
auth.processResponse();

EE9 and later usage looks like this:

import com.onelogin.saml2.servlet.jakarta.JakartaSamlHttpRequest;
import com.onelogin.saml2.servlet.jakarta.JakartaSamlHttpResponse;

final HttpRequest request = JakartaSamlHttpRequest.makeHttpRequest(jakartaServletRequest);
final HttpResponse response = JakartaSamlHttpResponse.makeHttpResponse(jakartaServletResponse);

final Auth auth = new Auth(saml2Settings, request, response);
auth.processResponse();

delegate.getSession().invalidate();
}

public static HttpRequest makeHttpRequest(HttpServletRequest delegate) {
Copy link
Author

@markkolich markkolich Mar 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not even sure this static method is really needed, I mean is this really any better than new JakartaSamlHttpRequest(delegate)?

delegate.sendRedirect(location);
}

public static HttpResponse makeHttpResponse(HttpServletResponse delegate) {
Copy link
Author

@markkolich markkolich Mar 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not even sure this static method is really needed, I mean is this really any better than new JakartaSamlHttpResponse(delegate)?

public final class HttpRequest {

public static final Map<String, List<String>> EMPTY_PARAMETERS = Collections.<String, List<String>>emptyMap();
public interface HttpRequest {
Copy link
Author

@markkolich markkolich Mar 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK calling this interface SamlHttpRequest or OneLoginSamlHttpRequest if the existing name is too generic.

Three implementors in this PR:

image

*
* @since 3.0.0
*/
public interface HttpResponse {
Copy link
Author

@markkolich markkolich Mar 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK calling this interface SamlHttpResponse or OneLoginSamlHttpResponse if the existing name is too generic.

Two implementors in this PR:

image

@pitbulk
Copy link
Contributor

pitbulk commented Mar 14, 2023

Thanks @markkolich for this PR. Let's see what rest of the people think about it.

@veselov, @mauromol, @jeroenvs, @lounagen, @krzysztof-osiecki , @dsvensson, @josemgut, @bramhaag, @fanste

@bramhaag
Copy link

This works for me. Thank you @markkolich!

@jeroenvs
Copy link

This would also work for me. Thank you!

@fanste
Copy link

fanste commented Mar 14, 2023

Thats seems to be the best solution instead of using the "transformer hack". Thanks for your work, @markkolich.

@josemgut
Copy link

This is also good for me. I'm not able to test it inmediatelly, but in two weeks we will apply it and it will work for sure. Thanks a lot.

@mauromol
Copy link
Contributor

I had a quick look at the commit and I would say this is exactly what I had in mind in #349 (comment). So, good job @markkolich

Just my 2 cents: maybe the invalidateSession() implementations could use delegate.getSession(false) and test the result against null before invalidating? Otherwise if, for whatever reason, no session exists, that method would uselessly create a new one to immediately invalidate it...

@markkolich
Copy link
Author

@mauromol fair point on invalidateSession() - I left it as is because the original logic prior to this refactor was:

request.getSession().invalidate();

Happy to change that to:

HttpSession session = delegate.getSession(false);
if (session != null) {
  session.invalidate();   
}

@kush-vi
Copy link

kush-vi commented Apr 26, 2023

will this be merged anytime soon ?

@ardeleana
Copy link

@markkolich
We encounter a NPE when using the processSLO because "SAMLRequest" param does not exist in request, that makes getParameters of the HttpRequest return null and isEmpty is directly applied on the null values object in getParameter method of HttpRequest.
NB1: we are using a sample app deployed in payara 6 app server and the jakarta servlet version.
NB2: we have fixed the issue in a particular fork that we'll use temporary, until this pull req will be merged and released
Stacktrace:
jakarta.enterprise.web|_ThreadID=82;_ThreadName=http-thread-pool::http-listener-1(3);_TimeMillis=1683800617926;_LevelValue=900;|
  StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception
java.lang.NullPointerException
        at com.onelogin.saml2.http.HttpRequest.getParameter(HttpRequest.java:48)
        at com.onelogin.saml2.Auth.processSLO(Auth.java:1269)
        at com.onelogin.saml2.Auth.processSLO(Auth.java:1371)
        at com.onelogin.saml2.Auth.processSLO(Auth.java:1380)
        at org.apache.jsp.sls_jsp._jspService(sls_jsp.java:113)

@markkolich
Copy link
Author

markkolich commented May 12, 2023

Nice find @ardeleana - I have fixed the bug in this PR and have updated the unit tests accordingly. Thank you!

@pitbulk there were also a bunch of LogoutRequest's used in tests that were coded to expire (NotOnOrAfter) on 2023-05-10. As I write this it's now 2023-05-12 and so those tests started failing. I have fixed that test data as well in this PR.

@markkolich
Copy link
Author

@mauromol I've been tinkering with the changes you suggested above. I think I understand what you're suggesting, and now that it's implemented the JavaxSamlAuth extends BaseAuth and JakartaSamlAuth extends BaseAuth approach looks like this...

Before:

<%@page import="com.onelogin.saml2.Auth"%>

<?
Auth auth = new Auth(request, response);
?>

After, with the BaseAuth approach discussed above in the thread:

<%@page import="com.onelogin.saml2.BaseAuth"%>
<%@page import="com.onelogin.saml2.servlet.jakarka.JakartaSamlAuth"%>

<?
BaseAuth auth = new JakartaSamlAuth(request, response);
?>

To gently reiterate, this is not a drop-in and make-no-changes to your JSPs backwards compatible change. Users will have to change imports and rename Auth -> BaseAuth. Is that acceptable?

I've pushed the suggested changes to this PR as a separate commit - I can squash if this looks good.

@markkolich
Copy link
Author

@pitbulk @mauromol any update here?

@ak98neon
Copy link

@pitbulk @mauromol please review

@mauromol
Copy link
Contributor

I just would like to specify that I'm not a maintainer of this project and I cannot merge. Some years ago I would have needed java-saml to be enhanced to properly support Italian SPID system, I've submitted some PRs, most of which have been merged, a couple of them are still there and one was never opened. Unfortunately, OneLogin lost interest in this project, Sixto changed his job, the new maintainers were absent, I even applied myself after being suggested by one of them, but things went in a different way. Probably this project should have been forked at that time, but I didn't have the necessary experience to do that. Now Sixto has come back as an independent maintainer, but it's clear that it is very low priority for him. I myself have changed job and I'm not into SAML and SPID any more, the latter now being pushed towards a migration to OpenID Connect, by the way (if it doesn't get dismissed before).

Here I just tried to give my suggestions on how to implement this based on what I know about Sixto point of view, and what I would have done myself. I still believe a solution which does not require any code change for old code should be possible, but I also think that small adjustments could probably be made by Sixto himself if he's willing to.

So, if I were you, I would seriously consider to fork this project and push the necessary changes the way you prefer.

@pitbulk
Copy link
Contributor

pitbulk commented Dec 30, 2023

It is not a matter of low priority, I'm sorry about the big delay I gave to this project.

As people may know, I maintain in my spare time not only java-saml, but php-saml, ruby-saml and python3-saml. And at the end of the day, it is a matter of time.

I had in mind to push this project in December, but sadly I have had not the chance to do it yet.
I was and I'm always open to collaboration and appreciate the effort you guys are spending in the PRs and suggestions you are sending.

@dsvensson
Copy link

You can probably spot 1-2 people in this thread who you can give merge access to to get the ball rolling. No harm in merging and then iterating, throw out a rc and get heated feedback.

@dsvensson
Copy link

@pitbulk Perhaps a bit to subtle given the lack of reply, but scrolling up here both @haavar (who mentioned being open to maintaining a fork) and @markkolich both sound like potential co-maintainers?

@arunkumarun
Copy link

@pitbulk Need this dependency for Wildfly Server version >= 27.

Waiting this to be merged.

@jacqueskpoty
Copy link

@markkolich coul you folllow up with comments so this PR can be merge?

@markkolich
Copy link
Author

@jacqueskpoty no, I am not a maintainer of this library ... I have no merge permissions, I'm just a contributor who opened this PR. Please followup with @pitbulk.

@jacqueskpoty
Copy link

@pitbulk Is this PR going to be merged any time soon?

Copy link

@haavar haavar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we completely remove the HttpRequest from core? I don't think it's too much to ask that the user extract the parameters and pass it to the library. That seems easier than for the user to understand how to configure the library for their version of the servlet API.


import org.apache.commons.lang3.StringUtils;

public class HttpRequestUtils {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this class used anywhere in core. It should either be moved or removed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used in toolkit but not core.

However, I kept the utils in core so that they stay near the HttpRequest and HttpResponse interfaces given the close relationship between these classes and their usage:

image

import java.util.HashMap;
import java.util.Map;

public class HttpResponseUtils {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see this class used anywhere in core. It should either be moved or removed.

@@ -625,7 +625,7 @@ public String login(String relayState, AuthnRequestParams authnRequestParams, Bo
parameters.put("SAMLRequest", samlRequest);

if (relayState == null) {
relayState = ServletUtils.getSelfRoutedURLNoQuery(request);
relayState = HttpRequestUtils.getSelfRoutedURLNoQuery(request);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@haavar The HttpRequestUtils class is being used here and is heavily used throughout this BaseAuth class.

@markkolich
Copy link
Author

I don't think it's too much to ask that the user extract the parameters and pass it to the library. That seems easier than for the user to understand how to configure the library for their version of the servlet API.

@haavar I disagree, but feel free to send a PR to my fork (e.g., markkolich#1) with your proposed changes and we can review+discuss.

@Jing-Van
Copy link

Jing-Van commented Jun 6, 2024

Hi @markkolich, is there an ETA for release, please?
When will 3.0.0 be available on Maven, please? Thank you.

com.onelogin
java-saml
3.0.0


com.onelogin
java-saml-servlet-jakarta
3.0.0

@Jing-Van
Copy link

Jing-Van commented Jun 7, 2024

Hi @pitbulk, sorry for asking again.
How is it going? Do you have some idea when will the jakarta supported available on maven, Thank you.

@thiagohora
Copy link

Any estimation on when will this be merged?

@Jing-Van
Copy link

Jing-Van commented Jun 13, 2024

Hi @dsvensson, @markkolich @pitbulk

Is it correct understanding that after #395 merged, I am able to pull com.onelogin 3.0 from Maven which supports jakarta?
What's the status now, how much longer to achieve that?
Is it the full pull request?
https://github.com/SAML-Toolkits/java-saml/pull/395/files#diff-1d18ce5e578972573311127e5969a1b6711cbcfbf3143a3fceee8b7a4e6cbb03

On pull request list, I saw #379 but not #395
#379

@markkolich
Do you have a #395 branch I can check out?
I can try build local lib for testing.
And how to potentially contribute to this project?
Thank you.

@markkolich
Copy link
Author

@Jing-Van I have no idea what #397 is about ... feel free to fork this repo and open your own PR. Just don't expect it to be merged lol 😃

As stated above, I am not a maintainer of this library and I have no merge permissions. I'm just a contributor who opened a PR over a weekend to try and address #349 and #115 which was blocking Jakarta adoption in a few of my projects.

Anyways, please read up on the current status of java-saml as a project in #388. Some good context there on where things stand.

@Jing-Van
Copy link

Hi @markkolich ,

sorry,
I mean #395.

I plan to migrate it to support jakarta.

Do you know is there a branch which tracked the most updated contributes from #349 #115 and #388?
May I have your email address, please or we continue discussing here for now.

Thank you.

@pitbulk
Copy link
Contributor

pitbulk commented Jun 20, 2024

@markkolich , @dsvensson , @mauromol, @haavar let's solve this situation.

Please, if you are interested in becoming a maintainer/collaborator of the Java-Saml toolkit, send me an email to the address in my Github Profile and share your availability with me for next week, to have a meeting.

Let's discuss the next steps and a roadmap to revive this project.

@Jing-Van
Copy link

I am in.

@markkolich , @dsvensson , @mauromol, @haavar let's solve this situation.

Please, if you are interested in becoming a maintainer/collaborator of the Java-Saml toolkit, send me an email to the address in my Github Profile and share your availability with me for next week, to have a meeting.

Let's discuss the next steps and a roadmap to revive this project.

@Jing-Van
Copy link

Hi,

@markkolich , @dsvensson , @mauromol, @haavar, @pitbulk
Based on profile,
Me and @markkolich are both PST time zone.
@pitbulk and @dsvensson are both Central European Summer Time
9am PST is 6pm Central European Summer Time.
Is that a good time for everyone? If we all need to meet online.
I am probably the latest into this thread, I have checked the markkolich:master and I am studying the source code now.

Thank you.

@haavar
Copy link

haavar commented Jun 25, 2024

I'm on PDT, and 9AM PDT works for me, but I'm pretty flexible.

@Jing-Van
Copy link

Hi @markkolich

I checked out https://github.com/markkolich/java-saml/tree/master

Currently there are tests which fail and some owasp issues.
What's the status now?
I was thinking to build a local libs of
java-saml-servlet-jakarta
java-saml
java-saml-core
as temp solutions.

I believe it should take less time than using a new lib such as keycloak.

Can you shed some lights?
If I go through source code, fix bug one by one. How far am I?
If the long solution is not too far away, then work on long solution directly.

Thank you.
ERROR] Failed to execute goal org.owasp:dependency-check-maven:8.4.0:check (default) on project java-saml-core:
[ERROR]
[ERROR] One or more dependencies were identified with vulnerabilities that have a CVSS score greater than or equal to '7.0':
[ERROR]
[ERROR] azure-core-1.46.0.jar: CVE-2023-36052(8.6)
[ERROR] azure-core-http-netty-1.14.0.jar: CVE-2023-36052(8.6)
[ERROR] azure-identity-1.13.0.jar: CVE-2023-36415(8.8), CVE-2023-36052(8.6)
[ERROR] azure-json-1.1.0.jar: CVE-2023-36052(8.6)
[ERROR] logback-core-1.4.7.jar: CVE-2023-6378(7.5)
[ERROR]

@Jing-Van
Copy link

Built my own libs for now :)

My 2 cents.
You can treat it as a java project and migrate to support jakarta similarly as if you were migrating your other java project.
Samilar methodologies applies.
You can make one work during the time before the official release come out.

If you are already using this library, switching to others such as Keycloak introduces significant changes and is unlikely to be implemented within 1-2 weeks, especially if you are already loaded with daily tasks and lack dedicated hours for it.

@anjana-midgard
Copy link

Any idea, by when this change will be available in maven ?

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

Successfully merging this pull request may close these issues.