Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions api/src/org/labkey/api/security/AuthFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,9 @@ else if (!AppProps.getInstance().isDevMode())
}

if (null == user)
{
if (AppProps.getInstance().isOptionalFeatureEnabled(AppProps.EXPERIMENTAL_NO_GUESTS))
user = User.nobody;
else
user = User.guest;
}
user = getGuestUser();
else
UserManager.updateRecentUser(user.isImpersonated() ? user.getImpersonatingUser() : user); // TODO: Sanity check this with Matt... treat impersonating admin as active, not impersonated user
UserManager.updateRecentUser(user.isImpersonated() ? user.getImpersonatingUser() : user);

req = AuthenticatedRequest.create(req, user);

Expand Down Expand Up @@ -262,7 +257,13 @@ private void addRandomHeader(HttpServletRequest req, HttpServletResponse resp)
resp.addHeader("X-LK-NONCE", sb.toString());
}


public static User getGuestUser()
{
if (AppProps.getInstance().isOptionalFeatureEnabled(AppProps.EXPERIMENTAL_NO_GUESTS))
return User.nobody;
else
return User.guest;
}

private boolean clearRequestAttributes(HttpServletRequest request)
{
Expand Down
13 changes: 8 additions & 5 deletions api/src/org/labkey/api/security/AuthenticatedRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,12 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
* User: matthewb
* Date: Feb 5, 2009
*/
public class AuthenticatedRequest extends HttpServletRequestWrapper implements AutoCloseable
{
private static final Logger _log = LogManager.getLogger(AuthenticatedRequest.class);

private final User _user;

private boolean _loggedIn;
private HttpSession _session = null;

Expand All @@ -76,11 +73,17 @@ public static AuthenticatedRequest create(@NotNull HttpServletRequest request, @

private AuthenticatedRequest(@NotNull HttpServletRequest request, @NotNull User user)
{
super(request instanceof AuthenticatedRequest ? (HttpServletRequest)((AuthenticatedRequest)request).getRequest() : request);
super(request instanceof AuthenticatedRequest authRequest ? authRequest.getRequest() : request);
_user = user;
_loggedIn = !_user.isGuest();
}

@Override
public HttpServletRequest getRequest()
{
return (HttpServletRequest)super.getRequest();
}

@Override
public void close()
{
Expand Down
50 changes: 43 additions & 7 deletions api/src/org/labkey/api/security/AuthenticationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ public ModelAndView getView(FORM form, BindException errors) throws Exception
}
else
{
HttpServletRequest request = getViewContext().getRequest();
HttpServletRequest request = getViewContext().getRequestOrThrow();

final PrimaryAuthenticationResult primaryResult;

Expand Down Expand Up @@ -1619,6 +1619,11 @@ public URLHelper getRedirectURL()


public static @NotNull AuthenticationResult handleAuthentication(HttpServletRequest request, Container c)
{
return handleAuthentication(request, c, true);
}

public static @NotNull AuthenticationResult handleAuthentication(HttpServletRequest request, Container c, boolean setSession)
{
HttpSession session = request.getSession(true);
PrimaryAuthenticationResult primaryAuthResult = AuthenticationManager.getPrimaryAuthenticationResult(session);
Comment thread
labkey-adam marked this conversation as resolved.
Expand Down Expand Up @@ -1686,13 +1691,16 @@ public URLHelper getRedirectURL()
LoginReturnProperties properties = getLoginReturnProperties(request);
URLHelper url = getAfterLoginURL(c, properties, primaryAuthUser);

// Prep the new session and set the user & authentication-related attributes
session = SecurityManager.setAuthenticatedUser(request, primaryAuthResult.getResponse(), primaryAuthUser, true);

if (session.isNew() && !primaryAuthUser.isGuest())
if (setSession)
{
// notify the websocket clients a new http session for the user has been started
NotificationService.get().sendServerEvent(primaryAuthUser.getUserId(), AuthNotify.LoggedIn);
// Prep the new session and set the user & authentication-related attributes
session = SecurityManager.setAuthenticatedUser(request, primaryAuthResult.getResponse(), primaryAuthUser, true);

if (session.isNew() && !primaryAuthUser.isGuest())
{
// notify the websocket clients a new http session for the user has been started
NotificationService.get().sendServerEvent(primaryAuthUser.getUserId(), AuthNotify.LoggedIn);
}
}

// Set the authentication validators into the new session
Expand Down Expand Up @@ -1759,6 +1767,34 @@ public static URLHelper getWelcomeURL()
return new URLHelper(true);
}

public record Reauth(String token, User user){}
public static final String REAUTH_TOKEN_NAME = "reauthToken";

public static @Nullable User getAndClearReauthUser(HttpServletRequest request, @Nullable String token)
{
if (token != null)
{
HttpSession session = request.getSession(false);

if (session != null)
{
Reauth reauth = (Reauth) session.getAttribute(REAUTH_TOKEN_NAME);
Comment thread
labkey-adam marked this conversation as resolved.

if (reauth != null)
{
boolean matches = token.equals(reauth.token());

if (matches)
{
session.removeAttribute(REAUTH_TOKEN_NAME);
return reauth.user();
}
}
}
}

return null;
}

// test() method should return true if the authentication is still valid
public interface AuthenticationValidator extends Predicate<HttpServletRequest>
Expand Down
1 change: 1 addition & 0 deletions api/src/org/labkey/api/security/LoginUrls.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public interface LoginUrls extends UrlProvider
ActionURL getLoginURL(URLHelper returnUrl);
ActionURL getRegisterURL(Container c, @Nullable URLHelper returnUrl);
ActionURL getLoginURL(Container c, @Nullable URLHelper returnUrl);
ActionURL getForceReauthURL(Container c, @Nullable URLHelper returnUrl);
ActionURL getLogoutURL(Container c);
ActionURL getLogoutURL(Container c, URLHelper returnUrl);
ActionURL getStopImpersonatingURL(Container c, @Nullable URLHelper returnUrl);
Expand Down
4 changes: 2 additions & 2 deletions api/src/org/labkey/api/view/RedirectException.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
/**
* When thrown in the context of an HTTP request, sends the client a *temporary* redirect in the HTTP response. Not
* treated as a loggable error. See {@link PermanentRedirectException} if a permanent redirect is desired.
* Note: This always redirects to the local server. If an external redirect is needed (this is rare), use
* {@link ExternalRedirectException} or (even rarer) {@link UnsafeExternalRedirectException}.
* Note: Instances of this specific class always redirect to the local server. If an external redirect is needed (this
* is rare), use {@link ExternalRedirectException} or (even rarer) {@link UnsafeExternalRedirectException}.
*/
public class RedirectException extends RuntimeException implements SkipMothershipLogging
{
Expand Down
5 changes: 2 additions & 3 deletions api/src/org/labkey/api/view/UnauthorizedException.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@
*/
package org.labkey.api.view;

import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.Nullable;

import jakarta.servlet.http.HttpServletResponse;

/**
* Signals to the HTTP client that the request is not authorized, via a 401 status code.
*/
Expand All @@ -30,7 +29,7 @@ public class UnauthorizedException extends HttpStatusException
/** Options for how the client should be informed of not being allowed to see a resource */
public enum Type
{
/** Redirect the browser to a different URL to render a login form */
/** If user is guest, redirect the browser to the login page */
redirectToLogin,
/** Send a 401, but signal that the server would accept HTTP BasicAuth credentials */
sendBasicAuth,
Expand Down
7 changes: 7 additions & 0 deletions api/src/org/labkey/api/view/ViewContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ public HttpServletRequest getRequest()
return _request;
}

public @NotNull HttpServletRequest getRequestOrThrow()
{
if (null == _request)
throw new IllegalStateException("Request is null");

return _request;
}

public void setRequest(HttpServletRequest request)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ public class ContentSecurityPolicyFilter implements Filter
private String _stashedTemplate = null;

// We can't set this statically because the class is referenced before URLProviders are available
@SuppressWarnings("DataFlowIssue")
private final String _reportingEndpointsHeaderValue = "csp-report=\"" + PageFlowUtil.urlProvider(AdminUrls.class).getCspReportToURL().getLocalURIString() + "\"";

// Initialized on first request and reset when allowed sources change. Don't reference this directly; always use
Expand Down
2 changes: 1 addition & 1 deletion assay/src/org/labkey/assay/AssayIntegrationTestCase.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@
updated.put("ResultProp", 200);
updated.put("RowId", resultRowId);
errors = new BatchValidationException();
Thread.sleep(5); // SQL Server timestamps aren't granular enough to guarantee different modified time
Thread.sleep(schema.getDbSchema().getSqlDialect().isSqlServer() ? 100 : 5); // SQL Server timestamps aren't granular enough to guarantee different modified time
resultsQUS.updateRows(user, c, Collections.singletonList(updated), null, errors, null, null);

// verify result created matches run's created in query table, but result modified now differs from run's created
Expand Down
Loading