Skip to content

Commit

Permalink
Fixes 16587 - support custom principal in Jakarta Authentication
Browse files Browse the repository at this point in the history
Signed-off-by: Arjan Tijms <arjan.tijms@gmail.com>
  • Loading branch information
arjantijms committed Mar 28, 2022
1 parent 410d0d9 commit c73f56b
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -307,6 +307,19 @@ private void processCallerPrincipal(CallerPrincipalCallback cpCallback) {
final Subject fs = cpCallback.getSubject();
Principal principal = cpCallback.getPrincipal();

// See if we need to wrap back the principal. This looks weird, but is needed for the
// check to re-use that is done below to work.
if (principal != null && !(principal instanceof WebPrincipal)) {
Principal sessionPrincipal = SecurityContext.getCurrent().getSessionPrincipal();
if (sessionPrincipal instanceof WebPrincipal) {
WebPrincipal webPrincipalFromSession = (WebPrincipal) sessionPrincipal;

if (webPrincipalFromSession.getCustomPrincipal() == principal) {
principal = webPrincipalFromSession;
}
}
}

if (principal instanceof WebPrincipal) {
WebPrincipal wp = (WebPrincipal) principal;
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -84,6 +85,10 @@ public SecurityContext getSecurityContext() {
return securityContext;
}

public Principal getCustomPrincipal() {
return customPrincipal;
}

@Override
public String getName() {
if (customPrincipal == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 Contributors to the Eclipse Foundation.
* Copyright 2021, 2022 Contributors to the Eclipse Foundation.
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -80,6 +80,7 @@
import org.apache.catalina.HttpResponse;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.authenticator.AuthenticatorBase;
import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.realm.Constants;
Expand Down Expand Up @@ -479,8 +480,11 @@ public boolean invokeAuthenticateDelegate(HttpRequest request, HttpResponse resp
// Jakarta Authentication is enabled for this application
try {
context.fireContainerEvent(BEFORE_AUTHENTICATION, null);
RequestFacade requestFacade = (RequestFacade) request.getRequest();
SecurityContext.getCurrent().setSessionPrincipal(requestFacade.getRequestPrincipal());
return validate(request, response, config, authenticator, calledFromAuthenticate);
} finally {
SecurityContext.getCurrent().setSessionPrincipal(null);
context.fireContainerEvent(AFTER_AUTHENTICATION, null);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -17,27 +18,43 @@

package org.apache.catalina.connector;

import org.apache.catalina.LogFacade;
import java.io.BufferedReader;
import java.io.IOException;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.SecurityPermission;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import org.apache.catalina.Globals;
import org.apache.catalina.LogFacade;
import org.apache.catalina.core.RequestFacadeHelper;
import org.apache.catalina.security.SecurityUtil;

import jakarta.servlet.*;
import com.sun.enterprise.security.web.integration.WebPrincipal;

import jakarta.servlet.AsyncContext;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletConnection;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletMapping;
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 jakarta.servlet.http.PushBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.SecurityPermission;
import java.util.*;
import jakarta.servlet.http.HttpServletMapping;


/**
Expand Down Expand Up @@ -837,12 +854,30 @@ public boolean isUserInRole(String role) {
}

@Override
public java.security.Principal getUserPrincipal() {
public Principal getUserPrincipal() {

if (request == null) {
throw new IllegalStateException(rb.getString(LogFacade.CANNOT_USE_REQUEST_OBJECT_OUTSIDE_SCOPE_EXCEPTION));
}

Principal principal = request.getUserPrincipal();
if (principal instanceof WebPrincipal) {
WebPrincipal webPrincipal = (WebPrincipal) principal;
if (webPrincipal.getCustomPrincipal() != null) {
principal = webPrincipal.getCustomPrincipal();
}
}

return principal;
}

// returns the original, unwrapped principal from the underlying request
public Principal getRequestPrincipal() {
if (request == null) {
throw new IllegalStateException(rb.getString(LogFacade.CANNOT_USE_REQUEST_OBJECT_OUTSIDE_SCOPE_EXCEPTION));
}


return request.getUserPrincipal();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
Expand Down Expand Up @@ -46,6 +47,9 @@
*
* This class is used on the server side to represent the security context.
*
* Class is a concept introduced in JDK1.0.
* Thread is a concept introduced in JDK1.0.
* Principal is a concept introduced in JDK1.1.
* Thread Local Storage is a concept introduced in JDK1.2.
*
* @see java.lang.ThreadLocal
Expand All @@ -71,6 +75,8 @@ public class SecurityContext extends AbstractSecurityContext {
// Did the client log in as or did the server generate the context
private boolean SERVER_GENERATED_SECURITY_CONTEXT = false;

private Principal sessionPrincipal;

/* This creates a new SecurityContext object.
* Note: that the docs for Subject state that the internal sets
* (eg. the principal set) cannot be modified unless the caller
Expand Down Expand Up @@ -352,6 +358,14 @@ public String toString() {
return "SecurityContext[ " + "Initiator: " + initiator + "Subject " + subject + " ]";
}

public Principal getSessionPrincipal() {
return sessionPrincipal;
}

public void setSessionPrincipal(Principal sessionPrincipal) {
this.sessionPrincipal = sessionPrincipal;
}

public Set<Principal> getPrincipalSet() {
return subject.getPrincipals();
}
Expand Down

0 comments on commit c73f56b

Please sign in to comment.