Skip to content

Commit

Permalink
Introduce capability to set the servletUri to be used by the OAuthCon…
Browse files Browse the repository at this point in the history
…figuration (#375)

* * Introducing log traces.
* Introducing capability to set the servletUri to be used by the
OAuthConfiguration

* plus change log

* newline fix

* a change from "error" to "trace" in one of the logs.

* Changed log level for some logs.

* javadocs fix

* Provide a default implementation for getServletUri()
  • Loading branch information
Jad-el-khoury authored Jul 31, 2023
1 parent ca9239c commit 57d32b6
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## [5.2.0-SNAPSHOT]

### Added
- Introducing capability to set the servletUri to be used by the OAuthConfiguration

### Changed

Expand Down
6 changes: 6 additions & 0 deletions server/oauth-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
</properties>

<dependencies>
<!-- Lyo Dependencies -->
<dependency>
<groupId>org.eclipse.lyo.oslc4j.core</groupId>
<artifactId>lyo-core-settings</artifactId>
<version>${v.lyo}</version>
</dependency>
<!-- Project specific -->
<dependency>
<groupId>jakarta.ws.rs</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import net.oauth.server.OAuthServlet;

import org.eclipse.lyo.server.oauth.core.consumer.LyoOAuthConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Validates that a request is authorized. The request must contain a valid
Expand All @@ -51,6 +53,8 @@
* @author Samuel Padgett
*/
public class OAuthRequest {
private static final Logger log = LoggerFactory.getLogger(OAuthRequest.class);

private HttpServletRequest httpRequest;
private OAuthMessage message;
private OAuthAccessor accessor;
Expand Down Expand Up @@ -122,12 +126,16 @@ public LyoOAuthConsumer getConsumer() {
* @throws OAuthException if the request fails validation
*/
public void validate() throws OAuthException, IOException, ServletException {
log.trace("validating the request.");
try {
OAuthConfiguration config = OAuthConfiguration.getInstance();
config.getValidator().validateMessage(message, accessor);
config.getTokenStrategy().validateAccessToken(this);
} catch (URISyntaxException e) {
throw new ServletException(e);
} catch (OAuthProblemException e) {
log.warn("OAuthProblemException caught when validating the request. {}", e.toString());
throw e;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import net.oauth.http.HttpMessage;
import net.oauth.server.OAuthServlet;

import org.eclipse.lyo.oslc4j.core.OSLC4JUtils;
import org.eclipse.lyo.server.oauth.core.Application;
import org.eclipse.lyo.server.oauth.core.AuthenticationException;
import org.eclipse.lyo.server.oauth.core.OAuthConfiguration;
Expand Down Expand Up @@ -184,6 +185,18 @@ protected void logout(Connection loginSession, HttpSession session) {
*/
abstract protected ConsumerStore createConsumerStore() throws Exception;

/**
* Gets the official servlet URL
* in case this can differ from that in the individual requests.
* @see org.eclipse.lyo.server.oauth.core.OAuthConfiguration#setServletUri(String)
* This is the typical implementation, which assumes {@link OSLC4JUtils#setPublicURI(String) OSLC4JUtils.setPublicURI(String)}
* and {@link OSLC4JUtils#setServletPath(String) OSLC4JUtils.setServletPath(String)}
* are first used to set the servlet URL.
*/
protected String getServletUri() {
return OSLC4JUtils.getServletURI();
}

/**
* Check if the resource is protected
*
Expand Down Expand Up @@ -288,85 +301,110 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
boolean isTwoLeggedOAuthRequest = false;
String twoLeggedOAuthConsumerKey = null;

log.trace("CredentialsFilter - RequestURL: {} {} on session {}", request.getMethod(), request.getRequestURL().toString(), request.getSession().getId());

//TODO: possibly do this in web.xml
if (isProtectedResource(request))
{
log.trace("{} on session {} - A protected resource", request.getPathInfo(), request.getSession().getId());

// First check if this is an OAuth request.
try {
try {
OAuthMessage message = OAuthServlet.getMessage(request, null);
log.trace("{} on session {} - checking for oauth1 authentication", request.getPathInfo(), request.getSession().getId());
// test if this is a valid two-legged oauth request
if ("".equals(message.getToken())) {
log.trace("{} on session {} - an oauth1 token with empty-value is found. checking for TwoLeggedOAuth", request.getPathInfo(), request.getSession().getId());
validateTwoLeggedOAuthMessage(message);
log.trace("{} on session {} - It is a TwoLeggedOAuthRequest", request.getPathInfo(), request.getSession().getId());
isTwoLeggedOAuthRequest = true;
twoLeggedOAuthConsumerKey = message.getConsumerKey();
}

if (!isTwoLeggedOAuthRequest && message.getToken() != null) {
log.trace("{} on session {} - an oauth1 token is found. Validating it.", request.getPathInfo(), request.getSession().getId());
OAuthRequest oAuthRequest = new OAuthRequest(request);
oAuthRequest.validate();
log.debug("{} on session {} - an oauth1 token is valid", request.getPathInfo(), request.getSession().getId());
Connection connector = tokenToConnectionCache.get(message.getToken());
if (connector == null) {
log.debug("{} on session {} - an oauth1 token is valid, but no Connector is associated with it. Raising an exception TOKEN_REJECTED", request.getPathInfo(), request.getSession().getId());
throw new OAuthProblemException(
OAuth.Problems.TOKEN_REJECTED);
}

log.debug("{} on session {} - oauth1 authentication is valid. Done. Binding the Connector to the session", request.getPathInfo(), request.getSession().getId());
request.getSession().setAttribute(CONNECTOR_ATTRIBUTE, connector);
}
} catch (OAuthProblemException e) {
log.warn("{} on session {} - OAuthProblemException caught. {}", request.getPathInfo(), e.toString());
if (OAuth.Problems.TOKEN_REJECTED.equals(e.getProblem()))
throwInvalidExpiredException(e);
else
throw e;
}
} catch (OAuthException e) {
log.error("{} on session {} - OOAuthException caught.", request.getPathInfo(), request.getSession().getId());
OAuthServlet.handleException(response, e, getOAuthRealm());
return;
} catch (URISyntaxException e) {
log.error("{} on session {} - URISyntaxException caught.", request.getPathInfo(), request.getSession().getId());
throw new ServletException(e);
}

// Check for Basic authentication if this is not an OAuth request
HttpSession session = request.getSession();
Connection connector = (Connection) session.getAttribute(CONNECTOR_ATTRIBUTE);
if (connector == null) {
// Check for Basic authentication. This is not an OAuth request (If it was, then earlier code would have set the connector to a non-null value)
log.trace("{} on session {} - checking for basic authentication", request.getPathInfo(), request.getSession().getId());
try {
Credentials credentials;
if (isTwoLeggedOAuthRequest) {
log.trace("{} on session {} - This is TwoLeggedOAuthRequest. Dealing wiht it.", request.getPathInfo(), request.getSession().getId());
connector = tokenToConnectionCache.get("");
if (connector == null) {
credentials = getCredentialsForOAuth(OAUTH_EMPTY_TOKEN_KEY, twoLeggedOAuthConsumerKey);
connector = login(credentials, request);
tokenToConnectionCache.put("", connector);
}
credentials = null; // TODO; Do we need to keep the credentials for this path ??
log.debug("{} on session {} - This is TwoLeggedOAuthRequest. Done dealing wiht it.", request.getPathInfo(), request.getSession().getId());
} else {
log.trace("{} on session {} - This is NOT TwoLeggedOAuthRequest.", request.getPathInfo(), request.getSession().getId());
log.trace("{} on session {} - Tring to find credentials in session or request", request.getPathInfo(), request.getSession().getId());
credentials = (Credentials) request.getSession().getAttribute(CREDENTIALS_ATTRIBUTE);
if (credentials == null)
{
log.trace("{} on session {} - No credentials found in session.", request.getPathInfo(), request.getSession().getId());
credentials = getCredentialsFromRequest(request);
if (credentials == null) {
log.trace("{} on session {} - No credentials found in request.", request.getPathInfo(), request.getSession().getId());
log.debug("{} on session {} - This is an UnauthorizedRequest. Handing the request as such", request.getPathInfo(), request.getSession().getId());
boolean interruptFilterChain = handleUnauthorizedRequest(request, response);
if (interruptFilterChain) {
return;
}
}
}
log.debug("{} on session {} - Credentials found in session or request.", request.getPathInfo(), request.getSession().getId());
log.trace("{} on session {} - Use Credentials to login and create a Connector.", request.getPathInfo(), request.getSession().getId());
connector = login(credentials, request);
}

log.debug("{} on session {} - Authentication is valid. Done. Binding the Connector & Credentials to the session", request.getPathInfo(), request.getSession().getId());
session.setAttribute(CONNECTOR_ATTRIBUTE, connector);
session.setAttribute(CREDENTIALS_ATTRIBUTE, credentials);

} catch (UnauthorizedException e)
{
sendUnauthorizedResponse(response, e);
//TODO: Change to a log message.
log.debug("UnauthorizedException occured while checking for Basic authentication");
//Do not call chain.doFilter().
return;
log.debug("{} - UnauthorizedException occured while checking for Basic authentication", request.getPathInfo(), request.getSession().getId());
sendUnauthorizedResponse(response, e);
//Do not call chain.doFilter().
return;
} catch (ServletException ce)
{
log.trace("{} - ServletException occured while checking for Basic authentication", request.getPathInfo(), request.getSession().getId());
throw ce;
}
}
Expand All @@ -377,6 +415,9 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
}

}
else {
log.trace("{} on session {} - A unprotected resource", request.getPathInfo(), request.getSession().getId());
}
}

chain.doFilter(servletRequest, servletResponse);
Expand Down Expand Up @@ -432,6 +473,7 @@ private void validateTwoLeggedOAuthMessage(OAuthMessage message)
accessor.tokenSecret = "";
config.getValidator().validateMessage(message, accessor);
} else {
log.error("OAuth.Problems.TOKEN_REJECTED");
throw new OAuthProblemException(
OAuth.Problems.TOKEN_REJECTED);
}
Expand Down Expand Up @@ -540,8 +582,11 @@ public void generateAccessToken(OAuthRequest oAuthRequest)
// For now, hard-code the consumers.
config.setConsumerStore(createConsumerStore());
} catch (Throwable t) {
System.err.println("Error initializing the OAuth consumer store: " + t.getMessage());
log.error("Error initializing the OAuth consumer store: " + t.getMessage());
}

config.setServletUri(getServletUri());
log.info("OauthConfig is working with ServletUri: {}", config.getServletUri());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,23 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Checks requests to see if they have the right X-CSRF-Prevent header values.
*
* @author Samuel Padgett
*/
public class CSRFPrevent {
private static final String CSRF_PREVENT_HEADER = "X-CSRF-Prevent";

public static void check(HttpServletRequest httpRequest) {
private static final Logger log = LoggerFactory.getLogger(CSRFPrevent.class);

public static void check(HttpServletRequest httpRequest) {
String csrfPrevent = httpRequest.getHeader(CSRF_PREVENT_HEADER);
String sessionId = httpRequest.getSession().getId();
if (!sessionId.equals(csrfPrevent)) {
log.warn("Request denied due to possible CSRF attack. Expected X-CSRF-Prevent header: {}. Received: {}", sessionId, csrfPrevent);
throw new WebApplicationException(Response.status(Status.FORBIDDEN)
.entity("Request denied due to possible CSRF attack.").type(MediaType.TEXT_PLAIN).build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,12 +460,13 @@ protected boolean confirmCallback(OAuthRequest oAuthRequest) throws OAuthExcepti
protected OAuthRequest validateRequest() throws OAuthException, IOException {
OAuthRequest oAuthRequest = new OAuthRequest(httpRequest);
try {
// log.trace("baseString: {} signature: {}", OAuthSignatureMethod.getBaseString(oAuthRequest.getMessage()),
// oAuthRequest.getMessage().getSignature());
OAuthValidator validator = OAuthConfiguration.getInstance().getValidator();
validator.validateMessage(oAuthRequest.getMessage(), oAuthRequest.getAccessor());
} catch (URISyntaxException e) {
throw new WebApplicationException(e, Status.INTERNAL_SERVER_ERROR);
} catch (OAuthProblemException e) {
log.error("OAuthProblemException caught when validating the request. {}", e.toString());
throw e;
}
return oAuthRequest;
}
Expand Down

0 comments on commit 57d32b6

Please sign in to comment.