Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-10.0.x-…
Browse files Browse the repository at this point in the history
…4919-WebSocketContainerStop

Signed-off-by: Lachlan Roberts <[email protected]>
  • Loading branch information
lachlan-roberts committed Jul 24, 2020
2 parents 695d239 + 9f3864a commit e13d26a
Show file tree
Hide file tree
Showing 46 changed files with 1,255 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

Expand All @@ -46,18 +48,33 @@
*/
public class DigestAuthentication extends AbstractAuthentication
{
private final Random random;
private final String user;
private final String password;

/**
/** Construct a DigestAuthentication with a {@link SecureRandom} nonce.
* @param uri the URI to match for the authentication
* @param realm the realm to match for the authentication
* @param user the user that wants to authenticate
* @param password the password of the user
*/
public DigestAuthentication(URI uri, String realm, String user, String password)
{
this(uri, realm, user, password, new SecureRandom());
}

/**
* @param uri the URI to match for the authentication
* @param realm the realm to match for the authentication
* @param user the user that wants to authenticate
* @param password the password of the user
* @param random the Random generator to use for nonces.
*/
public DigestAuthentication(URI uri, String realm, String user, String password, Random random)
{
super(uri, realm);
Objects.requireNonNull(random);
this.random = random;
this.user = user;
this.password = password;
}
Expand Down Expand Up @@ -216,7 +233,6 @@ private String nextNonceCount()

private String newClientNonce()
{
Random random = new Random();
byte[] bytes = new byte[8];
random.nextBytes(bytes);
return toHexString(bytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.jetty.client.AsyncContentProvider;
Expand Down Expand Up @@ -102,15 +101,10 @@ public MultiPartContentProvider(String boundary)

private static String makeBoundary()
{
Random random = new Random();
StringBuilder builder = new StringBuilder("JettyHttpClientBoundary");
int length = builder.length();
while (builder.length() < length + 16)
{
long rnd = random.nextLong();
builder.append(Long.toString(rnd < 0 ? -rnd : rnd, 36));
}
builder.setLength(length + 16);
builder.append(Long.toString(System.identityHashCode(builder), 36));
builder.append(Long.toString(System.identityHashCode(Thread.currentThread()), 36));
builder.append(Long.toString(System.nanoTime(), 36));
return builder.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ As well as opening the connectors as `root`, you can also have Jetty start the S
____

. A native code library is required to perform user switching.
This code is hosted as part of the Jetty ToolChain project and is released independently from Jetty itself.
You can find the source code https://github.com/eclipsejetty.toolchain[here] in the https://github.com/eclipse/jetty.toolchain/jetty-setuid[jetty-setuid] project.
This code is hosted as part of the https://github.com/eclipse/jetty.toolchain[Jetty ToolChain] project and is released independently from Jetty itself.
You can find the source code in the https://github.com/eclipse/jetty.toolchain/tree/master/jetty-setuid[eclipse/jetty.toolchain/jetty-setuid] project.
Build it locally, which will produce a native library appropriate for the operating system:
+
[source, screen, subs="{sub-order}"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b
}

// Attempt to login with the provided authCode
OpenIdCredentials credentials = new OpenIdCredentials(authCode, getRedirectUri(request), _configuration);
OpenIdCredentials credentials = new OpenIdCredentials(authCode, getRedirectUri(request));
UserIdentity user = login(null, credentials, request);
if (user != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.util.FormRequestContent;
Expand All @@ -38,7 +37,7 @@
*
* <p>
* This is constructed with an authorization code from the authentication request. This authorization code
* is then exchanged using {@link #redeemAuthCode(HttpClient)} for a response containing the ID Token and Access Token.
* is then exchanged using {@link #redeemAuthCode(OpenIdConfiguration)} for a response containing the ID Token and Access Token.
* The response is then validated against the {@link OpenIdConfiguration}.
* </p>
*/
Expand All @@ -48,16 +47,14 @@ public class OpenIdCredentials implements Serializable
private static final long serialVersionUID = 4766053233370044796L;

private final String redirectUri;
private final OpenIdConfiguration configuration;
private String authCode;
private Map<String, Object> response;
private Map<String, Object> claims;

public OpenIdCredentials(String authCode, String redirectUri, OpenIdConfiguration configuration)
public OpenIdCredentials(String authCode, String redirectUri)
{
this.authCode = authCode;
this.redirectUri = redirectUri;
this.configuration = configuration;
}

public String getUserId()
Expand All @@ -75,7 +72,25 @@ public Map<String, Object> getResponse()
return response;
}

public void redeemAuthCode(HttpClient httpClient) throws Exception
public boolean isExpired()
{
if (authCode != null || claims == null)
return true;

// Check expiry
long expiry = (Long)claims.get("exp");
long currentTimeSeconds = (long)(System.currentTimeMillis() / 1000F);
if (currentTimeSeconds > expiry)
{
if (LOG.isDebugEnabled())
LOG.debug("OpenId Credentials expired {}", this);
return true;
}

return false;
}

public void redeemAuthCode(OpenIdConfiguration configuration) throws Exception
{
if (LOG.isDebugEnabled())
LOG.debug("redeemAuthCode() {}", this);
Expand All @@ -84,7 +99,7 @@ public void redeemAuthCode(HttpClient httpClient) throws Exception
{
try
{
response = claimAuthCode(httpClient, authCode);
response = claimAuthCode(configuration);
if (LOG.isDebugEnabled())
LOG.debug("response: {}", response);

Expand All @@ -103,7 +118,7 @@ public void redeemAuthCode(HttpClient httpClient) throws Exception
claims = JwtDecoder.decode(idToken);
if (LOG.isDebugEnabled())
LOG.debug("claims {}", claims);
validateClaims();
validateClaims(configuration);
}
finally
{
Expand All @@ -113,22 +128,22 @@ public void redeemAuthCode(HttpClient httpClient) throws Exception
}
}

private void validateClaims()
private void validateClaims(OpenIdConfiguration configuration)
{
// Issuer Identifier for the OpenID Provider MUST exactly match the value of the iss (issuer) Claim.
if (!configuration.getIssuer().equals(claims.get("iss")))
throw new IllegalArgumentException("Issuer Identifier MUST exactly match the iss Claim");

// The aud (audience) Claim MUST contain the client_id value.
validateAudience();
validateAudience(configuration);

// If an azp (authorized party) Claim is present, verify that its client_id is the Claim Value.
Object azp = claims.get("azp");
if (azp != null && !configuration.getClientId().equals(azp))
throw new IllegalArgumentException("Authorized party claim value should be the client_id");
}

private void validateAudience()
private void validateAudience(OpenIdConfiguration configuration)
{
Object aud = claims.get("aud");
String clientId = configuration.getClientId();
Expand All @@ -150,25 +165,8 @@ else if (!isValidType)
throw new IllegalArgumentException("Audience claim was not valid");
}

public boolean isExpired()
{
if (authCode != null || claims == null)
return true;

// Check expiry
long expiry = (Long)claims.get("exp");
long currentTimeSeconds = (long)(System.currentTimeMillis() / 1000F);
if (currentTimeSeconds > expiry)
{
if (LOG.isDebugEnabled())
LOG.debug("OpenId Credentials expired {}", this);
return true;
}

return false;
}

private Map<String, Object> claimAuthCode(HttpClient httpClient, String authCode) throws Exception
@SuppressWarnings("unchecked")
private Map<String, Object> claimAuthCode(OpenIdConfiguration configuration) throws Exception
{
Fields fields = new Fields();
fields.add("code", authCode);
Expand All @@ -177,7 +175,7 @@ private Map<String, Object> claimAuthCode(HttpClient httpClient, String authCode
fields.add("redirect_uri", redirectUri);
fields.add("grant_type", "authorization_code");
FormRequestContent formContent = new FormRequestContent(fields);
Request request = httpClient.POST(configuration.getTokenEndpoint())
Request request = configuration.getHttpClient().POST(configuration.getTokenEndpoint())
.body(formContent)
.timeout(10, TimeUnit.SECONDS);
ContentResponse response = request.send();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import javax.security.auth.Subject;
import javax.servlet.ServletRequest;

import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.server.UserIdentity;
Expand All @@ -43,7 +42,6 @@ public class OpenIdLoginService extends ContainerLifeCycle implements LoginServi

private final OpenIdConfiguration configuration;
private final LoginService loginService;
private final HttpClient httpClient;
private IdentityService identityService;
private boolean authenticateNewUsers;

Expand All @@ -63,7 +61,6 @@ public OpenIdLoginService(OpenIdConfiguration configuration, LoginService loginS
{
this.configuration = configuration;
this.loginService = loginService;
this.httpClient = configuration.getHttpClient();
addBean(this.configuration);
addBean(this.loginService);
}
Expand All @@ -88,7 +85,7 @@ public UserIdentity login(String identifier, Object credentials, ServletRequest
OpenIdCredentials openIdCredentials = (OpenIdCredentials)credentials;
try
{
openIdCredentials.redeemAuthCode(httpClient);
openIdCredentials.redeemAuthCode(configuration);
if (openIdCredentials.isExpired())
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,11 @@ public Bundle getBundle()
public Enumeration<URL> getResources(String name) throws IOException
{
Enumeration<URL> osgiUrls = _osgiBundleClassLoader.getResources(name);
if (osgiUrls != null && osgiUrls.hasMoreElements())
return osgiUrls;

Enumeration<URL> urls = super.getResources(name);
List<URL> resources = toList(osgiUrls, urls);
return Collections.enumeration(resources);
return urls;
}

@Override
Expand Down
1 change: 1 addition & 0 deletions jetty-osgi/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<module>jetty-osgi-boot-warurl</module>
<module>jetty-osgi-httpservice</module>
<module>test-jetty-osgi-webapp</module>
<module>test-jetty-osgi-webapp-resources</module>
<module>test-jetty-osgi-context</module>
<module>test-jetty-osgi-fragment</module>
<module>test-jetty-osgi-server</module>
Expand Down
91 changes: 91 additions & 0 deletions jetty-osgi/test-jetty-osgi-webapp-resources/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>10.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-osgi-webapp-resources</artifactId>
<name>OSGi Test :: Webapp With Resources</name>
<url>http://www.eclipse.org/jetty</url>
<packaging>war</packaging>
<properties>
<bundle-symbolic-name>${project.groupId}.webapp.resources</bundle-symbolic-name>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<!-- No point building javadoc on testing projects -->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<supportedProjectTypes>
<supportedProjectType>war</supportedProjectType>
</supportedProjectTypes>
<instructions>
<Export-Package>!com.acme*</Export-Package>
<Web-ContextPath>/</Web-ContextPath>
</instructions>
</configuration>
</plugin>
<!-- also make this webapp an osgi bundle -->
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<!-- must deploy: required for jetty-distribution -->
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Loading

0 comments on commit e13d26a

Please sign in to comment.