mirror of
https://github.com/bmlong137/alfresco-keycloak.git
synced 2025-09-10 14:11:09 +00:00
Fix Share working with recent Repository improvements
This commit is contained in:
@@ -1,2 +1,4 @@
|
||||
log4j.logger.${project.artifactId}=INFO
|
||||
log4j.logger.${project.artifactId}.deps=ERROR
|
||||
log4j.logger.${project.artifactId}.deps=ERROR
|
||||
log4j.logger.${project.artifactId}.deps.keycloak=ERROR
|
||||
log4j.logger.${project.artifactId}.deps.jboss=ERROR
|
@@ -75,7 +75,7 @@
|
||||
<constructor-arg value="cache.${moduleId}.ticketTokenCache" />
|
||||
</bean>
|
||||
|
||||
<bean id="webscript.de.acosix.${moduleId}.roles.get" class="${project.artifactId}.web.scripts.RolesGet" parent="webscript">
|
||||
<bean id="webscript.de.acosix.keycloak.roles.get" class="${project.artifactId}.web.scripts.RolesGet" parent="webscript">
|
||||
<property name="roleService" ref="${moduleId}.RoleService" />
|
||||
</bean>
|
||||
|
||||
|
@@ -109,14 +109,21 @@
|
||||
<property name="personService" ref="PersonService" />
|
||||
</bean>
|
||||
|
||||
<bean id="webscriptAuthenticationFilter" class="org.alfresco.web.app.servlet.WebScriptSSOAuthenticationFilter">
|
||||
<bean id="webscriptAuthenticationFilter" class="${project.artifactId}.authentication.KeycloakWebScriptSSOAuthenticationFilter">
|
||||
<property name="active" value="${keycloak.authentication.enabled}" />
|
||||
<property name="container" ref="webscripts.container" />
|
||||
<!-- via inheritance, filter has way more fields, but only the above are actually needed -->
|
||||
</bean>
|
||||
|
||||
<!-- need to override this to align userAttributeName in session with other SSO filters -->
|
||||
<!-- for some reason, Alfresco is really inconsistent here between BaseAuthenticationFilter.AUTHENTICATION_USER and AuthenticationDriver.AUTHENTICATION_USER -->
|
||||
<bean id="cookieBasedAuthenticationFilter" class="${project.artifactId}.authentication.KeycloakWebScriptCookieAuthenticationFilter">
|
||||
<property name="authenticationService" ref="AuthenticationService" />
|
||||
<property name="authenticationComponent" ref="AuthenticationComponent" />
|
||||
<property name="personService" ref="personService" />
|
||||
<property name="personService" ref="PersonService" />
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="transactionService" ref="TransactionService" />
|
||||
<property name="container" ref="webscripts.container" />
|
||||
<property name="authenticationComponent" ref="AuthenticationComponent" />
|
||||
<property name="remoteUserMapper" ref="RemoteUserMapper" />
|
||||
</bean>
|
||||
|
||||
<bean id="globalAuthenticationFilter" class="${project.artifactId}.authentication.KeycloakAuthenticationFilter">
|
||||
|
@@ -484,10 +484,6 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
|
||||
final SessionUser sessionUser = this.createUserEnvironment(session, userId);
|
||||
this.keycloakAuthenticationComponent.handleUserTokens(accessToken, keycloakSecurityContext.getIdToken(), true);
|
||||
|
||||
// need different attribute name than default for integration with web scripts framework
|
||||
// default attribute name seems to be no longer used
|
||||
session.setAttribute(AuthenticationDriver.AUTHENTICATION_USER, sessionUser);
|
||||
|
||||
this.authenticationListener.userAuthenticated(new KeycloakCredentials(accessToken));
|
||||
|
||||
// store tokens in cache as well for ticket validation
|
||||
@@ -529,6 +525,41 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
|
||||
chain.doFilter(requestWrapper, res);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected SessionUser createUserEnvironment(final HttpSession session, final String userName) throws IOException, ServletException
|
||||
{
|
||||
final SessionUser sessionUser = super.createUserEnvironment(session, userName);
|
||||
|
||||
// ensure all common attribute names are mapped
|
||||
// Alfresco is really inconsistent with these attribute names
|
||||
session.setAttribute(AuthenticationDriver.AUTHENTICATION_USER, sessionUser);
|
||||
session.setAttribute(BaseAuthenticationFilter.AUTHENTICATION_USER, sessionUser);
|
||||
|
||||
return sessionUser;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected SessionUser createUserEnvironment(final HttpSession session, final String userName, final String ticket,
|
||||
final boolean externalAuth) throws IOException, ServletException
|
||||
{
|
||||
final SessionUser sessionUser = super.createUserEnvironment(session, userName, ticket, externalAuth);
|
||||
|
||||
// ensure all common attribute names are mapped
|
||||
// Alfresco is really inconsistent with these attribute names
|
||||
session.setAttribute(AuthenticationDriver.AUTHENTICATION_USER, sessionUser);
|
||||
session.setAttribute(BaseAuthenticationFilter.AUTHENTICATION_USER, sessionUser);
|
||||
|
||||
return sessionUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a failed authentication via Keycloak.
|
||||
*
|
||||
@@ -607,10 +638,6 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
|
||||
LOGGER.trace("Skipping doFilter as filter is not active");
|
||||
skip = true;
|
||||
}
|
||||
else if (req.getAttribute(NO_AUTH_REQUIRED) != null)
|
||||
{
|
||||
LOGGER.trace("Skipping doFilter as filter higher up in chain determined authentication as not required");
|
||||
}
|
||||
else if (servletRequestUri.matches(KEYCLOAK_ACTION_URL_PATTERN))
|
||||
{
|
||||
LOGGER.trace("Explicitly not skipping doFilter as Keycloak action URL is being called");
|
||||
@@ -636,6 +663,14 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
|
||||
else if (this.allowTicketLogon && this.checkForTicketParameter(context, req, res))
|
||||
{
|
||||
LOGGER.trace("Skipping doFilter as user was authenticated by ticket URL parameter");
|
||||
skip = true;
|
||||
}
|
||||
// check no-auth flag (derived e.g. from checking if target web script requires authentication) only after all pre-emptive auth
|
||||
// request details have been checked
|
||||
else if (Boolean.TRUE.equals(req.getAttribute(NO_AUTH_REQUIRED)))
|
||||
{
|
||||
LOGGER.trace("Skipping doFilter as filter higher up in chain determined authentication as not required");
|
||||
skip = true;
|
||||
}
|
||||
else if (sessionUser != null)
|
||||
{
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2019 - 2020 Acosix GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.acosix.alfresco.keycloak.repo.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.alfresco.repo.SessionUser;
|
||||
import org.alfresco.repo.webdav.auth.AuthenticationDriver;
|
||||
import org.alfresco.repo.webdav.auth.BaseAuthenticationFilter;
|
||||
import org.alfresco.web.app.servlet.WebscriptCookieAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* This sub-class of the default web script cookie filter only exists to ensure the proper session attribute names are used for mapping the
|
||||
* authenticated session user.
|
||||
*
|
||||
* @author Axel Faust
|
||||
*/
|
||||
public class KeycloakWebScriptCookieAuthenticationFilter extends WebscriptCookieAuthenticationFilter
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected SessionUser createUserEnvironment(final HttpSession session, final String userName) throws IOException, ServletException
|
||||
{
|
||||
final SessionUser sessionUser = super.createUserEnvironment(session, userName);
|
||||
|
||||
// ensure all common attribute names are mapped
|
||||
// Alfresco is really inconsistent with these attribute names
|
||||
session.setAttribute(AuthenticationDriver.AUTHENTICATION_USER, sessionUser);
|
||||
session.setAttribute(BaseAuthenticationFilter.AUTHENTICATION_USER, sessionUser);
|
||||
|
||||
return sessionUser;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected SessionUser createUserEnvironment(final HttpSession session, final String userName, final String ticket,
|
||||
final boolean externalAuth) throws IOException, ServletException
|
||||
{
|
||||
final SessionUser sessionUser = super.createUserEnvironment(session, userName, ticket, externalAuth);
|
||||
|
||||
// ensure all common attribute names are mapped
|
||||
// Alfresco is really inconsistent with these attribute names
|
||||
session.setAttribute(AuthenticationDriver.AUTHENTICATION_USER, sessionUser);
|
||||
session.setAttribute(BaseAuthenticationFilter.AUTHENTICATION_USER, sessionUser);
|
||||
|
||||
return sessionUser;
|
||||
}
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2019 - 2020 Acosix GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package de.acosix.alfresco.keycloak.repo.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
import org.alfresco.repo.web.filter.beans.DependencyInjectedFilter;
|
||||
import org.alfresco.repo.webdav.auth.BaseAuthenticationFilter;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.web.app.servlet.WebScriptSSOAuthenticationFilter;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.extensions.surf.util.URLDecoder;
|
||||
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
|
||||
import org.springframework.extensions.webscripts.Match;
|
||||
import org.springframework.extensions.webscripts.RuntimeContainer;
|
||||
|
||||
/**
|
||||
* This web script SSO authentication filter class is used instead of {@link WebScriptSSOAuthenticationFilter default Alfresco filter} in
|
||||
* order to properly handle unauthenticated and guest access, especially since the later is performed by Alfresco Share to load edition
|
||||
* details and potentially other data needed for determining which customisations are active, even before a user has had a chance to
|
||||
* authenticate.
|
||||
*
|
||||
* @author Axel Faust
|
||||
*/
|
||||
public class KeycloakWebScriptSSOAuthenticationFilter extends BaseAuthenticationFilter
|
||||
implements DependencyInjectedFilter, InitializingBean, ActivateableBean
|
||||
{
|
||||
|
||||
// copied from WebScriptRequestImpl due to accessible constraints
|
||||
private static final String ARG_GUEST = "guest";
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(KeycloakWebScriptSSOAuthenticationFilter.class);
|
||||
|
||||
protected RuntimeContainer container;
|
||||
|
||||
protected boolean isActive = true;
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet()
|
||||
{
|
||||
PropertyCheck.mandatory(this, "container", this.container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param container
|
||||
* the container to set
|
||||
*/
|
||||
public void setContainer(final RuntimeContainer container)
|
||||
{
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates or deactivates the bean
|
||||
*
|
||||
* @param active
|
||||
* <code>true</code> if the bean is active and initialisation should complete
|
||||
*/
|
||||
public final void setActive(final boolean active)
|
||||
{
|
||||
this.isActive = active;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public final boolean isActive()
|
||||
{
|
||||
return this.isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(final ServletContext context, final ServletRequest sreq, final ServletResponse sresp, final FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
final HttpServletRequest req = (HttpServletRequest) sreq;
|
||||
|
||||
final String requestURI = req.getRequestURI();
|
||||
final String pathInfo = requestURI.substring((req.getContextPath() + req.getServletPath()).length());
|
||||
|
||||
LOGGER.trace("Processing request: {} SID: {}", requestURI, req.getSession(false) != null ? req.getSession().getId() : null);
|
||||
|
||||
final Match match = this.container.getRegistry().findWebScript(req.getMethod(), URLDecoder.decode(pathInfo));
|
||||
if (match != null && match.getWebScript() != null)
|
||||
{
|
||||
final RequiredAuthentication reqAuth = match.getWebScript().getDescription().getRequiredAuthentication();
|
||||
if (RequiredAuthentication.none == reqAuth)
|
||||
{
|
||||
LOGGER.debug("Found webscript with no authentication - set NO_AUTH_REQUIRED flag.");
|
||||
req.setAttribute(NO_AUTH_REQUIRED, Boolean.TRUE);
|
||||
}
|
||||
else if (RequiredAuthentication.guest == reqAuth && Boolean.parseBoolean(sreq.getParameter(ARG_GUEST)))
|
||||
{
|
||||
LOGGER.debug("Found webscript with guest authentication and request with set guest parameter - set NO_AUTH_REQUIRED flag.");
|
||||
req.setAttribute(NO_AUTH_REQUIRED, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
chain.doFilter(sreq, sresp);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
// ugh - Commons Logging - why does base class not have a sensible default??
|
||||
protected Log getLogger()
|
||||
{
|
||||
return LogFactory.getLog(this.getClass());
|
||||
}
|
||||
}
|
@@ -312,7 +312,7 @@ public class RoleServiceImpl implements InitializingBean, RoleService
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.debug("No role mapper defined for resource {}", roleNameMapper);
|
||||
LOGGER.debug("No role mapper defined for resource {}", resourceName);
|
||||
roles = Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user