diff --git a/.gitignore b/.gitignore index d93daae7..02fb8b07 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ target/ /.apt_generated/ .*.swp + +work-cognito/ +work-keycloak/ \ No newline at end of file diff --git a/pom.xml b/pom.xml index 175e662d..e10156a5 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.jenkins-ci.plugins plugin - 4.87 + 5.3 @@ -45,14 +45,14 @@ 4 999999-SNAPSHOT jenkinsci/${project.artifactId}-plugin - - 2.426.3 false Max 1836.vccda_4a_122a_a_e 4.383 - 5.7.7 + 6.1.0 + 6.1.14 + 2.18.1 @@ -64,16 +64,6 @@ pom import - - - com.nimbusds - nimbus-jose-jwt - 9.47 - - com.github.stephenc.jcip @@ -104,10 +94,17 @@ org.pac4j - - pac4j-javaee + pac4j-jakartaee ${pac4jVersion} + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + com.google.guava guava @@ -139,8 +136,18 @@ com.google.guava guava + + org.springframework + spring-core + + + org.springframework + spring-jcl + + + com.google.code.gson gson @@ -301,5 +308,4 @@ - diff --git a/src/main/java/org/jenkinsci/plugins/oic/AnythingGoesTokenValidator.java b/src/main/java/org/jenkinsci/plugins/oic/AnythingGoesTokenValidator.java index 2bdb56ca..6a165023 100644 --- a/src/main/java/org/jenkinsci/plugins/oic/AnythingGoesTokenValidator.java +++ b/src/main/java/org/jenkinsci/plugins/oic/AnythingGoesTokenValidator.java @@ -24,7 +24,7 @@ public class AnythingGoesTokenValidator extends TokenValidator { public static final Logger LOGGER = Logger.getLogger(AnythingGoesTokenValidator.class.getName()); public AnythingGoesTokenValidator() { - super(createFakeOidcConfiguration()); + super(createFakeOidcConfiguration(), createFakeProviderMetadata()); } @Override @@ -51,17 +51,25 @@ public IDTokenClaimsSet validate(final JWT idToken, final Nonce expectedNonce) { * So we need a configuration with this set just so the validator can say "this is valid". */ private static OidcConfiguration createFakeOidcConfiguration() { + OidcConfiguration config = new OidcConfiguration(); + config.setClientId("ignored"); + config.setSecret("ignored"); + config.setPreferredJwsAlgorithm(JWSAlgorithm.HS256); + config.setClientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC); + return config; + } + + /** + * Annoyingly the super class needs an OIDCProviderMetadata with some values set, + * which if we are not validating we may not actually have (e.g. jwks_url). + * So we need a metadata provider with this set just so the validator can say "this is valid". + */ + private static OIDCProviderMetadata createFakeProviderMetadata() { try { - OidcConfiguration config = new OidcConfiguration(); - config.setClientId("ignored"); - config.setSecret("ignored"); OIDCProviderMetadata providerMetadata = new OIDCProviderMetadata( new Issuer("http://ignored"), List.of(SubjectType.PUBLIC), new URI("http://ignored.and.invalid./")); providerMetadata.setIDTokenJWSAlgs(List.of(JWSAlgorithm.HS256)); - config.setProviderMetadata(providerMetadata); - config.setPreferredJwsAlgorithm(JWSAlgorithm.HS256); - config.setClientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC); - return config; + return providerMetadata; } catch (URISyntaxException e) { // should never happen the urls we are using are valid throw new IllegalStateException(e); diff --git a/src/main/java/org/jenkinsci/plugins/oic/CustomOidcConfiguration.java b/src/main/java/org/jenkinsci/plugins/oic/CustomOidcConfiguration.java index 5f1878b4..2700af24 100644 --- a/src/main/java/org/jenkinsci/plugins/oic/CustomOidcConfiguration.java +++ b/src/main/java/org/jenkinsci/plugins/oic/CustomOidcConfiguration.java @@ -39,6 +39,9 @@ public void configureHttpRequest(HTTPRequest request) { } } request.setProxy(proxy); + // super class will configure the hostname verifier and the SSL socket factory and the default values in case + // the config object doesn't have those values must be overrriden in case the disableTLS is true + super.configureHttpRequest(request); if (disableTLS) { request.setHostnameVerifier(IgnoringHostNameVerifier.INSTANCE); try { @@ -47,6 +50,5 @@ public void configureHttpRequest(HTTPRequest request) { throw new IllegalStateException("could not configure the SSLFactory, this should not be possible", e); } } - super.configureHttpRequest(request); } } diff --git a/src/main/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusion.java b/src/main/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusion.java index c888ed12..65ba3f8e 100644 --- a/src/main/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusion.java +++ b/src/main/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusion.java @@ -2,11 +2,11 @@ import hudson.Extension; import hudson.security.csrf.CrumbExclusion; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; /** * Excluding the escapeHatch login from CSRF protection as the crumb is calculated based on the authentication diff --git a/src/main/java/org/jenkinsci/plugins/oic/OicCrumbExclusion.java b/src/main/java/org/jenkinsci/plugins/oic/OicCrumbExclusion.java index d7e0141e..72f11e9f 100644 --- a/src/main/java/org/jenkinsci/plugins/oic/OicCrumbExclusion.java +++ b/src/main/java/org/jenkinsci/plugins/oic/OicCrumbExclusion.java @@ -3,11 +3,11 @@ import hudson.Extension; import hudson.security.SecurityRealm; import hudson.security.csrf.CrumbExclusion; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import jenkins.model.Jenkins; /** diff --git a/src/main/java/org/jenkinsci/plugins/oic/OicSecurityRealm.java b/src/main/java/org/jenkinsci/plugins/oic/OicSecurityRealm.java index ca151330..5dfc6301 100644 --- a/src/main/java/org/jenkinsci/plugins/oic/OicSecurityRealm.java +++ b/src/main/java/org/jenkinsci/plugins/oic/OicSecurityRealm.java @@ -46,7 +46,7 @@ import hudson.model.Descriptor.FormException; import hudson.model.Failure; import hudson.model.User; -import hudson.security.ChainedServletFilter; +import hudson.security.ChainedServletFilter2; import hudson.security.SecurityRealm; import hudson.tasks.Mailer; import hudson.util.FormValidation; @@ -55,6 +55,15 @@ import io.burt.jmespath.JmesPath; import io.burt.jmespath.RuntimeConfiguration; import io.burt.jmespath.jcf.JcfRuntime; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectStreamException; @@ -79,15 +88,6 @@ import java.util.logging.Logger; import java.util.regex.Pattern; import javax.annotation.PostConstruct; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; import jenkins.security.FIPS140; @@ -102,9 +102,11 @@ import org.kohsuke.stapler.Header; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.Stapler; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.interceptor.RequirePOST; +import org.pac4j.core.context.CallContext; +import org.pac4j.core.context.FrameworkParameters; import org.pac4j.core.context.WebContext; import org.pac4j.core.context.session.SessionStore; import org.pac4j.core.credentials.Credentials; @@ -114,11 +116,13 @@ import org.pac4j.core.http.callback.NoParameterCallbackUrlResolver; import org.pac4j.core.profile.creator.ProfileCreator; import org.pac4j.jee.context.JEEContextFactory; +import org.pac4j.jee.context.JEEFrameworkParameters; import org.pac4j.jee.context.session.JEESessionStoreFactory; import org.pac4j.jee.http.adapter.JEEHttpActionAdapter; import org.pac4j.oidc.client.OidcClient; import org.pac4j.oidc.config.OidcConfiguration; import org.pac4j.oidc.credentials.authenticator.OidcAuthenticator; +import org.pac4j.oidc.metadata.OidcOpMetadataResolver; import org.pac4j.oidc.profile.OidcProfile; import org.pac4j.oidc.redirect.OidcRedirectionActionBuilder; import org.springframework.security.authentication.AnonymousAuthenticationToken; @@ -172,23 +176,23 @@ ClientAuthenticationMethod toClientAuthenticationMethod() { @Deprecated private transient String wellKnownOpenIDConfigurationUrl; - /** @deprecated see {@link OicServerConfiguration#getTokenServerUrl()} */ + /** @deprecated see {@link OicServerManualConfiguration#getTokenServerUrl()} */ @Deprecated private transient String tokenServerUrl; - /** @deprecated see {@link OicServerConfiguration#getJwksServerUrl()} */ + /** @deprecated see {@link OicServerManualConfiguration#getJwksServerUrl()} */ @Deprecated private transient String jwksServerUrl; - /** @deprecated see {@link OicServerConfiguration#getTokenAuthMethod()} */ + /** @deprecated see {@link OicServerManualConfiguration#getTokenAuthMethod()} */ @Deprecated private transient TokenAuthMethod tokenAuthMethod; - /** @deprecated see {@link OicServerConfiguration#getAuthorizationServerUrl()} */ + /** @deprecated see {@link OicServerManualConfiguration#getAuthorizationServerUrl()} */ @Deprecated private transient String authorizationServerUrl; - /** @deprecated see {@link OicServerConfiguration#getUserInfoServerUrl()} */ + /** @deprecated see {@link OicServerManualConfiguration#getUserInfoServerUrl()} */ @Deprecated private transient String userInfoServerUrl; @@ -206,14 +210,14 @@ ClientAuthenticationMethod toClientAuthenticationMethod() { private transient String simpleGroupsFieldName = null; private transient String nestedGroupFieldName = null; - /** @deprecated see {@link OicServerConfiguration#getScopes()} */ + /** @deprecated see {@link OicServerManualConfiguration#getScopes()} */ @Deprecated private transient String scopes = null; private final boolean disableSslVerification; private boolean logoutFromOpenidProvider = true; - /** @deprecated see {@link OicServerConfiguration#getEndSessionUrl()} */ + /** @deprecated see {@link OicServerManualConfiguration#getEndSessionUrl()} */ @Deprecated private transient String endSessionEndpoint = null; @@ -517,11 +521,15 @@ private OidcConfiguration buildOidcConfiguration() { OIDCProviderMetadata oidcProviderMetadata = serverConfiguration.toProviderMetadata(); filterNonFIPS140CompliantAlgorithms(oidcProviderMetadata); + OidcOpMetadataResolver metadataResolver; if (this.isDisableTokenVerification()) { conf.setAllowUnsignedIdTokens(true); - conf.setTokenValidator(new AnythingGoesTokenValidator()); + metadataResolver = new OicdPluginOpMetadataResolver(conf, oidcProviderMetadata, true); + } else { + metadataResolver = new OicdPluginOpMetadataResolver(conf, oidcProviderMetadata, false); } - conf.setProviderMetadata(oidcProviderMetadata); + conf.setOpMetadataResolver(metadataResolver); + if (oidcProviderMetadata.getScopes() != null) { // auto configuration does not need to supply scopes conf.setScope(oidcProviderMetadata.getScopes().toString()); @@ -533,6 +541,8 @@ private OidcConfiguration buildOidcConfiguration() { conf.setResourceRetriever(getResourceRetriever()); if (this.isPkceEnabled()) { conf.setPkceMethod(CodeChallengeMethod.S256); + } else { + conf.setDisablePkce(true); } return conf; } @@ -853,7 +863,7 @@ public String getAuthenticationGatewayUrl() { @Override public Filter createFilter(FilterConfig filterConfig) { - return new ChainedServletFilter(super.createFilter(filterConfig), new Filter() { + return new ChainedServletFilter2(super.createFilter(filterConfig), new Filter() { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -933,7 +943,7 @@ protected String getValidRedirectUrl(String url) { } /** - * Handles the the securityRealm/commenceLogin resource and sends the user off to the IdP + * Handles the securityRealm/commenceLogin resource and sends the user off to the IdP * @param from the relative URL to the page that the user has just come from * @param referer the HTTP referer header (where to redirect the user back to after login has finished) * @throws URISyntaxException if the provided data is invalid @@ -947,12 +957,13 @@ public void doCommenceLogin(@QueryParameter String from, @Header("Referer") fina final String redirectOnFinish = getValidRedirectUrl(from != null ? from : referer); OidcRedirectionActionBuilder builder = new OidcRedirectionActionBuilder(client); - WebContext webContext = - JEEContextFactory.INSTANCE.newContext(Stapler.getCurrentRequest(), Stapler.getCurrentResponse()); - SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(); + FrameworkParameters frameworkParameters = + new JEEFrameworkParameters(Stapler.getCurrentRequest2(), Stapler.getCurrentResponse2()); + WebContext webContext = JEEContextFactory.INSTANCE.newContext(frameworkParameters); + SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(frameworkParameters); + CallContext callContext = new CallContext(webContext, sessionStore); RedirectionAction redirectionAction = - builder.getRedirectionAction(webContext, sessionStore).orElseThrow(); - + builder.getRedirectionAction(callContext).orElseThrow(); // store the redirect url for after the login. sessionStore.set(webContext, SESSION_POST_LOGIN_REDIRECT_URL_KEY, redirectOnFinish); JEEHttpActionAdapter.INSTANCE.adapt(redirectionAction, webContext); @@ -1149,7 +1160,7 @@ private List ensureString(Object field) { } @Restricted(DoNotUse.class) // stapler only - public void doLogout(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + public void doLogout(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); User user = User.get2(authentication); @@ -1172,7 +1183,7 @@ public void doLogout(StaplerRequest req, StaplerResponse rsp) throws IOException } @Override - public String getPostLogOutUrl2(StaplerRequest req, Authentication auth) { + public String getPostLogOutUrl2(StaplerRequest2 req, Authentication auth) { Object idToken = req.getAttribute(ID_TOKEN_REQUEST_ATTRIBUTE); Object state = getStateAttribute(req.getSession()); var openidLogoutEndpoint = maybeOpenIdLogoutEndpoint( @@ -1187,12 +1198,15 @@ public String getPostLogOutUrl2(StaplerRequest req, Authentication auth) { Object getStateAttribute(HttpSession session) { // return null; OidcClient client = buildOidcClient(); - WebContext webContext = - JEEContextFactory.INSTANCE.newContext(Stapler.getCurrentRequest(), Stapler.getCurrentResponse()); - SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(); + FrameworkParameters frameworkParameters = + new JEEFrameworkParameters(Stapler.getCurrentRequest2(), Stapler.getCurrentResponse2()); + WebContext webContext = JEEContextFactory.INSTANCE.newContext(frameworkParameters); + SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(frameworkParameters); + CallContext callContext = new CallContext(webContext, sessionStore); + return client.getConfiguration() .getValueRetriever() - .retrieve(client.getStateSessionAttributeName(), client, webContext, sessionStore) + .retrieve(callContext, client.getStateSessionAttributeName(), client) .orElse(null); } @@ -1219,7 +1233,7 @@ private String maybeOpenIdLogoutEndpoint(String idToken, String state, String po return null; } - private String getFinalLogoutUrl(StaplerRequest req, Authentication auth) { + private String getFinalLogoutUrl(StaplerRequest2 req, Authentication auth) { if (Jenkins.get().hasPermission(Jenkins.READ)) { return super.getPostLogOutUrl2(req, auth); } @@ -1256,11 +1270,13 @@ private String buildOAuthRedirectUrl() throws NullPointerException { * @param request The user's request * @throws ParseException if the JWT (or other response) could not be parsed. */ - public void doFinishLogin(StaplerRequest request, StaplerResponse response) throws IOException, ParseException { + public void doFinishLogin(StaplerRequest2 request, StaplerResponse2 response) throws IOException, ParseException { OidcClient client = buildOidcClient(); - WebContext webContext = JEEContextFactory.INSTANCE.newContext(request, response); - SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(); + FrameworkParameters frameworkParameters = new JEEFrameworkParameters(request, response); + WebContext webContext = JEEContextFactory.INSTANCE.newContext(frameworkParameters); + SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(frameworkParameters); + CallContext callContext = new CallContext(webContext, sessionStore); try { // NB: TODO this also handles back channel logout if "logoutendpoint" parameter is set @@ -1273,14 +1289,13 @@ public void doFinishLogin(StaplerRequest request, StaplerResponse response) thro throw new TechnicalException("Could not create a new session"); } - Credentials credentials = client.getCredentials(webContext, sessionStore) - .orElseThrow(() -> new Failure("Could not extract credentials from request")); + Credentials credentials = getCredentials(client, callContext); ProfileCreator profileCreator = client.getProfileCreator(); // creating the profile performs validation of the token OidcProfile profile = (OidcProfile) profileCreator - .create(credentials, webContext, sessionStore) + .create(callContext, credentials) .orElseThrow(() -> new Failure("Could not build user profile")); AccessToken accessToken = profile.getAccessToken(); @@ -1314,6 +1329,15 @@ public void doFinishLogin(StaplerRequest request, StaplerResponse response) thro } } + private Credentials getCredentials(OidcClient client, CallContext callContext) { + Credentials credentials = client.getCredentials(callContext) + .orElseThrow(() -> new Failure("Could not extract credentials from request")); + + return client.getAuthenticator() + .validate(callContext, credentials) + .orElseThrow(() -> new Failure("Could not " + "validate " + "credentials")); + } + /** * Handles Token Expiration. * @throws IOException a low level exception @@ -1375,8 +1399,9 @@ public boolean handleTokenExpiration(HttpServletRequest httpRequest, HttpServlet return true; } - private void redirectToLoginUrl(HttpServletRequest req, HttpServletResponse res) throws IOException { - if (req != null && (req.getSession(false) != null || Strings.isNullOrEmpty(req.getHeader("Authorization")))) { + private void redirectToLoginUrl(@NonNull HttpServletRequest req, @NonNull HttpServletResponse res) + throws IOException { + if (req != null && req.getSession(false) != null || Strings.isNullOrEmpty(req.getHeader("Authorization"))) { req.getSession().invalidate(); } if (res != null) { @@ -1388,7 +1413,6 @@ public boolean isExpired(OicCredentials credentials) { if (credentials.getExpiresAtMillis() == null) { return false; } - return CLOCK.millis() >= credentials.getExpiresAtMillis(); } @@ -1399,8 +1423,10 @@ private boolean refreshExpiredToken( HttpServletResponse httpResponse) throws IOException { - WebContext webContext = JEEContextFactory.INSTANCE.newContext(httpRequest, httpResponse); - SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(); + FrameworkParameters frameworkParameters = new JEEFrameworkParameters(httpRequest, httpResponse); + WebContext webContext = JEEContextFactory.INSTANCE.newContext(frameworkParameters); + SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(frameworkParameters); + CallContext callContext = new CallContext(webContext, sessionStore); OidcClient client = buildOidcClient(); // PAC4J maintains the nonce even though servers should not respond with an id token containing the nonce // https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokenResponse @@ -1416,7 +1442,7 @@ private boolean refreshExpiredToken( profile.setIdTokenString(credentials.getIdToken()); profile.setRefreshToken(new RefreshToken(credentials.getRefreshToken())); - profile = (OidcProfile) client.renewUserProfile(profile, webContext, sessionStore) + profile = (OidcProfile) client.renewUserProfile(callContext, profile) .orElseThrow(() -> new IllegalStateException("Could not renew user profile")); // During refresh the IDToken may or may not be present. diff --git a/src/main/java/org/jenkinsci/plugins/oic/OicdPluginOpMetadataResolver.java b/src/main/java/org/jenkinsci/plugins/oic/OicdPluginOpMetadataResolver.java new file mode 100644 index 00000000..84451124 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/oic/OicdPluginOpMetadataResolver.java @@ -0,0 +1,37 @@ +package org.jenkinsci.plugins.oic; + +import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata; +import org.pac4j.oidc.config.OidcConfiguration; +import org.pac4j.oidc.metadata.StaticOidcOpMetadataResolver; +import org.pac4j.oidc.profile.creator.TokenValidator; + +public class OicdPluginOpMetadataResolver extends StaticOidcOpMetadataResolver { + + private boolean allowsAnything; + + public OicdPluginOpMetadataResolver( + OidcConfiguration configuration, OIDCProviderMetadata staticMetadata, boolean allowsAnything) { + super(configuration, staticMetadata); + this.allowsAnything = allowsAnything; + } + + @Override + protected TokenValidator createTokenValidator() { + if (allowsAnything) { + return new AnythingGoesTokenValidator(); + } + + return super.createTokenValidator(); + } + + /** + * This method is needed as there seems to be a bug in pac4j and hasChanged is not able to return true + * This will make it work until the bug is fixed. + * Link to the bug: https://stackoverflow.com/questions/79126478/pac4j-returns-an-error-refreshing-an-expired-token + * TODO eventually remove + */ + @Override + public boolean hasChanged() { + return true; + } +} diff --git a/src/test/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusionTest.java b/src/test/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusionTest.java index e3155ef5..14b91baa 100644 --- a/src/test/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusionTest.java +++ b/src/test/java/org/jenkinsci/plugins/oic/EscapeHatchCrumbExclusionTest.java @@ -1,11 +1,11 @@ package org.jenkinsci.plugins.oic; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletResponse; import org.junit.Test; import static org.junit.Assert.assertFalse; diff --git a/src/test/java/org/jenkinsci/plugins/oic/MockHttpServletRequest.java b/src/test/java/org/jenkinsci/plugins/oic/MockHttpServletRequest.java index 5bb2836a..578f0554 100644 --- a/src/test/java/org/jenkinsci/plugins/oic/MockHttpServletRequest.java +++ b/src/test/java/org/jenkinsci/plugins/oic/MockHttpServletRequest.java @@ -1,24 +1,24 @@ package org.jenkinsci.plugins.oic; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpUpgradeHandler; +import jakarta.servlet.http.Part; import java.io.BufferedReader; import java.security.Principal; import java.util.Collection; import java.util.Enumeration; import java.util.Locale; import java.util.Map; -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; public class MockHttpServletRequest implements HttpServletRequest { diff --git a/src/test/java/org/jenkinsci/plugins/oic/OicCrumbExclusionTest.java b/src/test/java/org/jenkinsci/plugins/oic/OicCrumbExclusionTest.java index a6f0ad72..22ed2133 100644 --- a/src/test/java/org/jenkinsci/plugins/oic/OicCrumbExclusionTest.java +++ b/src/test/java/org/jenkinsci/plugins/oic/OicCrumbExclusionTest.java @@ -1,8 +1,8 @@ package org.jenkinsci.plugins.oic; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import jenkins.model.Jenkins; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/src/test/java/org/jenkinsci/plugins/oic/PluginTest.java b/src/test/java/org/jenkinsci/plugins/oic/PluginTest.java index 4d2fcb34..2b502218 100644 --- a/src/test/java/org/jenkinsci/plugins/oic/PluginTest.java +++ b/src/test/java/org/jenkinsci/plugins/oic/PluginTest.java @@ -18,6 +18,7 @@ import hudson.model.User; import hudson.tasks.Mailer; import hudson.util.VersionNumber; +import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; @@ -42,7 +43,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.net.ssl.SSLException; -import javax.servlet.http.HttpSession; import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; import jenkins.security.LastGrantedAuthoritiesProperty; @@ -147,7 +147,7 @@ public void testLoginWithDefaults() throws Exception { .withQueryParam("nonce", matching(".+"))); verify(postRequestedFor(urlPathEqualTo("/token")).withRequestBody(notMatching(".*&scope=.*"))); webClient.executeOnServer(() -> { - HttpSession session = Stapler.getCurrentRequest().getSession(); + HttpSession session = Stapler.getCurrentRequest2().getSession(); assertNotNull(((OicSecurityRealm) Jenkins.get().getSecurityRealm()).getStateAttribute(session)); return null; }); @@ -983,7 +983,7 @@ public void testLogoutShouldBeJenkinsOnlyWhenNoProviderLogoutConfigured() throws String[] logoutURL = new String[1]; jenkinsRule.executeOnServer(() -> { - logoutURL[0] = oicsr.getPostLogOutUrl2(Stapler.getCurrentRequest(), Jenkins.ANONYMOUS2); + logoutURL[0] = oicsr.getPostLogOutUrl2(Stapler.getCurrentRequest2(), Jenkins.ANONYMOUS2); return null; }); assertEquals("/jenkins/", logoutURL[0]); @@ -997,7 +997,7 @@ public void testLogoutShouldBeProviderURLWhenProviderLogoutConfigured() throws E String[] logoutURL = new String[1]; jenkinsRule.executeOnServer(() -> { - logoutURL[0] = oicsr.getPostLogOutUrl2(Stapler.getCurrentRequest(), Jenkins.ANONYMOUS2); + logoutURL[0] = oicsr.getPostLogOutUrl2(Stapler.getCurrentRequest2(), Jenkins.ANONYMOUS2); return null; }); assertEquals("http://provider/logout?state=null", logoutURL[0]); @@ -1014,7 +1014,7 @@ public void testLogoutShouldBeProviderURLWithRedirectWhenProviderLogoutConfigure String[] logoutURL = new String[1]; jenkinsRule.executeOnServer(() -> { - logoutURL[0] = oicsr.getPostLogOutUrl2(Stapler.getCurrentRequest(), Jenkins.ANONYMOUS2); + logoutURL[0] = oicsr.getPostLogOutUrl2(Stapler.getCurrentRequest2(), Jenkins.ANONYMOUS2); return null; }); assertEquals( diff --git a/src/test/java/org/jenkinsci/plugins/oic/TestRealm.java b/src/test/java/org/jenkinsci/plugins/oic/TestRealm.java index eec1d58e..4abcd960 100644 --- a/src/test/java/org/jenkinsci/plugins/oic/TestRealm.java +++ b/src/test/java/org/jenkinsci/plugins/oic/TestRealm.java @@ -8,11 +8,13 @@ import java.io.IOException; import java.io.ObjectStreamException; import java.text.ParseException; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; +import org.pac4j.core.context.FrameworkParameters; import org.pac4j.core.context.WebContext; import org.pac4j.core.context.session.SessionStore; import org.pac4j.jee.context.JEEContextFactory; +import org.pac4j.jee.context.JEEFrameworkParameters; import org.pac4j.jee.context.session.JEESessionStoreFactory; import org.pac4j.oidc.client.OidcClient; @@ -259,14 +261,15 @@ public Descriptor getDescriptor() { } @Override - public void doFinishLogin(StaplerRequest request, StaplerResponse response) throws IOException, ParseException { + public void doFinishLogin(StaplerRequest2 request, StaplerResponse2 response) throws IOException, ParseException { /* * PluginTest uses a hardCoded nonce "nonce" */ if (!isNonceDisabled()) { // only hack the nonce if the nonce is enabled - WebContext webContext = JEEContextFactory.INSTANCE.newContext(request, response); - SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(); + FrameworkParameters frameworkParameters = new JEEFrameworkParameters(request, response); + WebContext webContext = JEEContextFactory.INSTANCE.newContext(frameworkParameters); + SessionStore sessionStore = JEESessionStoreFactory.INSTANCE.newSessionStore(frameworkParameters); OidcClient oidcClient = buildOidcClient(); sessionStore.set(webContext, oidcClient.getNonceSessionAttributeName(), "nonce"); }