Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Authorization refactoring
Rename FedoraPolicyEnforcementPoint interface to FedoraAuthorizationDelegate.
Instead of passing principals to PEP/authorization delegates, pass the session instance.
User and group principals added as session attributes.
ServletContainerAuthenticationProvider adds the servlet request as a session attribute (so authorization classes can access request IP address, etc).
Changed FedoraUserSecurityContext constructor to take a Principal instance rather than ServletCredentials.
Added additional documentation for PEP/authz delegate and other methods.

Resolves: https://www.pivotaltracker.com/story/show/66946122
  • Loading branch information
daines authored and Andrew Woods committed Mar 7, 2014
1 parent 63fe103 commit 3bf9967
Show file tree
Hide file tree
Showing 31 changed files with 571 additions and 504 deletions.
@@ -0,0 +1,84 @@
/**
* Copyright 2013 DuraSpace, Inc.
*
* 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 org.fcrepo.auth.common;

import org.modeshape.jcr.value.Path;

import javax.jcr.Session;

/**
* An interface that can authorize access to specific resources within
* repositories.
* <p>
* An implementation has the opportunity to inspect nodes and the session, which
* may have additional information assigned as session attributes, such as the
* associated servlet request. This interface defines the Fedora-specific
* attributes which may be added.
* </p>
*
* @author Gregory Jansen
* @see org.fcrepo.auth.roles.common.AbstractRolesAuthorizationDelegate
* @see org.fcrepo.auth.roles.basic.BasicRolesAuthorizationDelegate
*/
public interface FedoraAuthorizationDelegate {

/**
* The name of the session attribute containing the servlet request (an
* instance of javax.servlet.http.HttpServletRequest).
*/
public static final String FEDORA_SERVLET_REQUEST =
"fedora-servlet-request";

/**
* The name of the session attribute containing an instance of Principal
* representing the current authenticated user.
*/
public static final String FEDORA_USER_PRINCIPAL = "fedora-user-principal";

/**
* The name of the session attribute containing a set of instances of
* Principal, representing the current user's credentials, including the
* value of the FEDORA_USER_PRINCIPAL session attribute.
*/
public static final String FEDORA_ALL_PRINCIPALS = "fedora-all-principals";

/**
* Determine if the supplied session has permission at absPath for all of
* the actions.
* <p>
* The authentication provider may have added session attributes, which can
* be accessed in implementations by calling session#getAttribute. If an
* attribute is not available in session attributes and would be required to
* establish that the session has permission for any action given, an
* implementation should usually return false.
* </p>
* <p>
* Note that accessing nodes using the provided session will result in
* additional calls to this method and thus an infinite loop. Instead,
* obtain a new session instance if your implementation requires access to
* nodes. See AbstractRolesAuthorizationDelegate for an example.
* </p>
*
* @param session
* @param absPath
* @param actions
* @return true if the given session has permission at absPath for all of
* the given actions, or false otherwise
*/
boolean hasPermission(Session session, Path absPath, String[] actions);

}

This file was deleted.

Expand Up @@ -18,21 +18,19 @@

import static org.fcrepo.auth.common.ServletContainerAuthenticationProvider.EVERYONE;

import java.security.Principal;
import java.util.Set;

import org.modeshape.jcr.api.ServletCredentials;
import org.modeshape.jcr.security.AdvancedAuthorizationProvider;
import org.modeshape.jcr.security.SecurityContext;
import org.modeshape.jcr.value.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.Principal;

/**
* The security context for Fedora servlet users. These users are not
* necessarily authenticated by the container, i.e. users may include the
* general public. This security context delegates all access decisions to the
* configured Fedora policy enforcement point.
* configured authorization delegate.
*
* @author Gregory Jansen
*/
Expand All @@ -42,33 +40,28 @@ public class FedoraUserSecurityContext implements SecurityContext,
private static final Logger LOGGER = LoggerFactory
.getLogger(FedoraUserSecurityContext.class);

private Set<Principal> principals = null;

private Principal userPrincipal = null;

private FedoraPolicyEnforcementPoint pep = null;
private FedoraAuthorizationDelegate fad = null;

private boolean loggedIn = true;

/**
* Constructs a new security context.
*
* @param request the servlet request
* @param principals security principals associated with this request
* @param pep the policy enforcement point
* @param userPrincipal the user principal associated with this security
* context
* @param fad the authorization delegate
*/
protected FedoraUserSecurityContext(
final ServletCredentials credentials,
final Set<Principal> principals,
final FedoraPolicyEnforcementPoint pep) {
this.principals = principals;
this.pep = pep;
if (credentials.getRequest() != null) {
this.userPrincipal = credentials.getRequest().getUserPrincipal();
}
if (this.pep == null) {
LOGGER.warn("This security context must have a PEP injected");
throw new IllegalArgumentException("This security context must have a PEP injected");
protected FedoraUserSecurityContext(final Principal userPrincipal,
final FedoraAuthorizationDelegate fad) {
this.fad = fad;
this.userPrincipal = userPrincipal;

if (this.fad == null) {
LOGGER.warn("This security context must have a FAD injected");
throw new IllegalArgumentException(
"This security context must have a FAD injected");
}
}

Expand Down Expand Up @@ -138,11 +131,7 @@ public void logout() {
* @see
* org.modeshape.jcr.security.AdvancedAuthorizationProvider#hasPermission
* (org.modeshape.jcr.security.AdvancedAuthorizationProvider.Context,
* org.modeshape.jcr.value.Path, java.lang.String[]) grabs AuthZ attributes
* from context and delegates to a handler class subject: user roles
* (abstract privileges?) group principals (on campus) (URIs? attrIds?) the
* user principle resource attributes: mix-in types JCR path environment
* attributes: ??
* org.modeshape.jcr.value.Path, java.lang.String[])
*/
@Override
public boolean hasPermission(final Context context, final Path absPath,
Expand All @@ -156,10 +145,9 @@ public boolean hasPermission(final Context context, final Path absPath,
return actions.length == 1 && "read".equals(actions[0]);
}

// delegate to Fedora PDP
if (pep != null) {
return pep.hasModeShapePermission(absPath, actions,
this.principals, getEffectiveUserPrincipal());
// delegate
if (fad != null) {
return fad.hasPermission(context.getSession(), absPath, actions);
}
return false;
}
Expand Down

This file was deleted.

Expand Up @@ -18,27 +18,25 @@

import static java.util.Collections.emptySet;

import javax.jcr.Credentials;

import java.security.Principal;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

/**
* An example principal factory that extracts groups principals from request
* headers.
*
* An example principal provider that extracts principals from request headers.
*
* @author Gregory Jansen
*/
public class HTTPHeaderPrincipalFactory implements HTTPPrincipalFactory {
public class HttpHeaderPrincipalProvider implements PrincipalProvider {

/*
* (non-Javadoc)
* @see
* org.fcrepo.auth.GroupPrincipalFactory#getGroupPrincipals(javax.servlet
* .http.HttpServletRequest)
* org.fcrepo.auth.PrincipalProvider#getPrincipals(javax.jcr.Credentials)
*/
@Override
public Set<Principal> getGroupPrincipals(final HttpServletRequest request) {
public Set<Principal> getPrincipals(final Credentials credentials) {
return emptySet();
}

Expand Down
@@ -0,0 +1,52 @@
/**
* Copyright 2013 DuraSpace, Inc.
*
* 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 org.fcrepo.auth.common;

import javax.jcr.Credentials;

import java.security.Principal;
import java.util.Set;

/**
* This interface provides a way for authentication code to communicate generic
* credentials to authorization delegates. An implementation of this interface
* could perform a query to determine group membership, for example.
* <p>
* The ServletContainerAuthenticationProvider may be configured with one or more
* implementations of this class, which it will consult during authentication.
* The results will be assigned to the FEDORA_ALL_PRINCIPALS session attribute.
* </p>
*
* @author Gregory Jansen
* @see HttpHeaderPrincipalProvider
*/
public interface PrincipalProvider {

/**
* Extract principals from the provided credentials.
* <p>
* If no principals can be extracted, for example because the credentials
* are of a different type than expected, implementations of this method
* should return the empty set rather than null.
* </p>
*
* @param credentials the credentials
* @return a set of security principals
*/
Set<Principal> getPrincipals(Credentials credentials);

}

0 comments on commit 3bf9967

Please sign in to comment.