Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MODE-1273 Added built-in authentication using Seam Security #199

Merged
merged 1 commit into from Sep 22, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -989,13 +989,23 @@ config.repository("repository A")
in the JAAS policy, or a &JaasCredentials; constructed with a specific and already-authenticated JAAS &LoginContext;.
This provider can be disabled by setting the <link linkend="jcr_repository_options">jaasLoginConfigName configuration option</link>
to an empty (i.e., zero-length) value; otherwise, the option defines the name of the JAAS login configuration and
will default to "modeshape-jcr" if not explicitly set.</para>
will default to "modeshape-jcr" if not explicitly set. (This provider also works in some J2EE containers, in which
the JAAS Subject is not available via the standard JAAS API and instead requires use of the JACC API, which many
J2EE containers support).</para>
</listitem>
<listitem>
<para>&SeamSecurityProvider; delegates all authentication and role-based authorization to the Seam Security framework.
This provider authenticates clients that login to the &Repository; with no need to pass a &Credentials; object.
Note this does require obtaining a session for each servlet request, which is actually how
the JCR API was intended to be used within web applications. This provider is automatically enabled when the
Seam Security Identity class is found on the classpath.</para>
</listitem>
<listitem>
<para>&ServletProvider; delegates all authentication and role-based authorization to the servlet framework.
This provider authenticates clients that login to the &Repository; with a &ServletCredentials; object, which can be constructed with the
&HttpServletRequest;. Note this does require obtaining a session for each servlet request, which is actually how
the JCR API was intended to be used within web applications.</para>
the JCR API was intended to be used within web applications. This provider is automatically enabled when the
HttpServletSession class is found on the classpath.</para>
</listitem>
<listitem>
<para>&AnonymousProvider; will allow clients without &Credentials; to operate upon the repository, and will
Expand All @@ -1010,8 +1020,8 @@ config.repository("repository A")
The &SecurityContextProvider; is also configured only when the
<link linkend="jcr_repository_options">useSecurityContextCredentials configuration option</link> is set to 'true'.
This provider authenticates clients that pass a &SecurityContextCredentials; object, and delegates all authentication to
the embedded SecurityContext. This deprecated approach not enabled by default, and will be removed in the next major release of ModeShape.
It remains in place to enable applications that use this approach to upgrade to ModeShape 2.6 (or later) without breaking their
the embedded SecurityContext. This deprecated approach is not enabled by default, and will be removed in the next major release of ModeShape.
It remains in place to enable applications that use this older and less attractive approach to upgrade to ModeShape 2.6 (or later) without breaking their
authentication mechanism.
</para>
</note>
Expand Down
1 change: 1 addition & 0 deletions docs/reference/src/main/docbook/en-US/custom.dtd
Expand Up @@ -255,6 +255,7 @@
<!ENTITY JaasProvider "<ulink url='&API;jcr/security/JaasProvider.html'><classname>JaasProvider</classname></ulink>">
<!ENTITY ServletProvider "<ulink url='&API;jcr/security/ServletProvider.html'><classname>ServletProvider</classname></ulink>">
<!ENTITY AnonymousProvider "<ulink url='&API;jcr/security/AnonymousProvider.html'><classname>AnonymousProvider</classname></ulink>">
<!ENTITY SeamSecurityProvider "<ulink url='&API;jcr/security/SeamSecurityProvider.html'><classname>SeamSecurityProvider</classname></ulink>">
<!ENTITY SecurityContextProvider "<ulink url='&API;jcr/security/SecurityContextProvider.html'><classname>SecurityContextProvider</classname></ulink>">
<!ENTITY AuthorizationProvider "<ulink url='&API;jcr/security/AuthorizationProvider.html'><classname>AuthorizationProvider</classname></ulink>">
<!ENTITY ModeShapePermissions "<ulink url='&API;jcr/ModeShapePermissions.html'><classname>ModeShapePermissions</classname></ulink>">
Expand Down
4 changes: 4 additions & 0 deletions modeshape-jcr/pom.xml
Expand Up @@ -71,6 +71,10 @@
<groupId>org.jboss.spec.javax.security.jacc</groupId>
<artifactId>jboss-jacc-api_1.4_spec</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam</artifactId>
</dependency>

<!--
Testing (note the scope)
Expand Down
18 changes: 16 additions & 2 deletions modeshape-jcr/src/main/java/org/modeshape/jcr/JcrRepository.java
Expand Up @@ -122,6 +122,7 @@
import org.modeshape.jcr.security.AuthenticationProviders;
import org.modeshape.jcr.security.JaasProvider;
import org.modeshape.jcr.security.JaccSubjectResolver;
import org.modeshape.jcr.security.SeamSecurityProvider;
import org.modeshape.jcr.security.SecurityContextProvider;
import org.modeshape.jcr.security.ServletProvider;
import org.modeshape.jcr.xpath.XPathQueryParser;
Expand Down Expand Up @@ -938,22 +939,34 @@ public RepositoryConnectionFactory getRepositoryConnectionFactory() {
try {
JaasProvider jaasProvider = new JaasProvider(policyName, subjectResolver);
authenticators = authenticators.with(jaasProvider);
LOGGER.debug("Enabling JAAS authentication and authorization.");
} catch (java.lang.SecurityException e) {
LOGGER.warn(JcrI18n.loginConfigNotFound, policyName, Option.JAAS_LOGIN_CONFIG_NAME, repositoryName());
} catch (javax.security.auth.login.LoginException e) {
LOGGER.warn(JcrI18n.loginConfigNotFound, policyName, Option.JAAS_LOGIN_CONFIG_NAME, repositoryName());
}
}

try {
// Try to set up the Seam Security provider ...
ClassUtil.loadClassStrict("org.jboss.seam.security.Identity");
SeamSecurityProvider seamSecurityProvider = new SeamSecurityProvider();
authenticators = authenticators.with(seamSecurityProvider);
LOGGER.debug("Enabling Seam Security authentication and authorization.");
} catch (ClassNotFoundException cnfe) {
// Must not be able to load the class ...
LOGGER.debug("Failed to find 'org.jboss.seam.security.Identity' class, so not loading ModeShape's optional SeamSecurityProvider");
}

try {
// Try to set up the HTTP servlet request class, which is available only in servlet containers ...
ClassUtil.loadClassStrict("javax.servlet.http.HttpServletRequest");
ServletProvider servletProvider = new ServletProvider();
authenticators = authenticators.with(servletProvider);
LOGGER.debug("Enabling optional servlet authentication.");
LOGGER.debug("Enabling servlet authentication and authorization.");
} catch (ClassNotFoundException cnfe) {
// Must not be able to load the class ...
LOGGER.debug("Failed to find 'javax.servlet.http.HttpServletRequest', so not loading 'o.m.j.security.ServletProvider'");
LOGGER.debug("Failed to find 'javax.servlet.http.HttpServletRequest' class, so not loading ModeShape's optional ServletProvider");
}

// Set up the anonymous provider (if appropriate) ...
Expand All @@ -966,6 +979,7 @@ public RepositoryConnectionFactory getRepositoryConnectionFactory() {
if (roles.size() > 0) {
AnonymousProvider anonProvider = new AnonymousProvider(ANONYMOUS_USER_NAME, roles);
authenticators = authenticators.with(anonProvider);
LOGGER.debug("Enabling anonymous authentication and authorization.");
}
}

Expand Down
@@ -0,0 +1,110 @@
/*
* ModeShape (http://www.modeshape.org)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
* individual contributors.
*
* ModeShape is free software. Unless otherwise indicated, all code in ModeShape
* is licensed to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* ModeShape is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.modeshape.jcr.security;

import java.util.Map;
import javax.jcr.Credentials;
import org.jboss.seam.security.Identity;
import org.modeshape.common.annotation.Immutable;
import org.modeshape.common.util.CheckArg;
import org.modeshape.graph.ExecutionContext;
import org.modeshape.graph.SecurityContext;

/**
* An implementation of {@link AuthenticationProvider} that uses Seam Security to perform all authentication and <i>role-based</i>
* authorization.
*/
public class SeamSecurityProvider implements AuthenticationProvider {

/**
* {@inheritDoc}
*
* @see org.modeshape.jcr.security.AuthenticationProvider#authenticate(javax.jcr.Credentials, java.lang.String,
* java.lang.String, org.modeshape.graph.ExecutionContext, java.util.Map)
*/
public ExecutionContext authenticate( Credentials credentials,
String repositoryName,
String workspaceName,
ExecutionContext repositoryContext,
Map<String, Object> sessionAttributes ) {
if (credentials == null) {
// We don't care about credentials, as we'll always use the Seam Identity class ...
Identity identity = Identity.instance();
if (identity != null && identity.isLoggedIn()) {
SeamSecurityContext context = new SeamSecurityContext(identity);
return repositoryContext.with(context);
}
}
return null;
}

/**
* A {@link SecurityContext security context} implementation that is based upon Seam Security and that provides authentication
* and authorization through the Seam Security {@link Identity} instance.
*/
@Immutable
public static class SeamSecurityContext implements SecurityContext {

private final Identity identity;

/**
* Create a {@link SeamSecurityContext} with the supplied {@link Identity} instance.
*
* @param identity the Seam Security {@link Identity} instance; may not be null
* @throws IllegalArgumentException if the <code>identity</code> is null
*/
public SeamSecurityContext( Identity identity ) {
CheckArg.isNotNull(identity, "identity");
this.identity = identity;
}

/**
* {@inheritDoc SecurityContext#getUserName()}
*
* @see SecurityContext#getUserName()
*/
public String getUserName() {
return identity.getCredentials().getUsername();
}

/**
* {@inheritDoc SecurityContext#hasRole(String)}
*
* @see SecurityContext#hasRole(String)
*/
public boolean hasRole( String roleName ) {
return identity.hasRole(roleName);
}

/**
* {@inheritDoc SecurityContext#logout()}
*
* @see SecurityContext#logout()
*/
public void logout() {
// we'll let Seam Security handle logging out of the Identity ...
}
}

}
8 changes: 8 additions & 0 deletions modeshape-parent/pom.xml
Expand Up @@ -222,6 +222,7 @@
<java.version.jcr.graph>1.5</java.version.jcr.graph>
<javax.servlet.version>2.5</javax.servlet.version>
<javax.jacc.version>1.0.0.Final</javax.jacc.version>
<jboss.seam.version>2.2.2.Final</jboss.seam.version>
<!--
Maven plugin versions
-->
Expand Down Expand Up @@ -1082,6 +1083,13 @@
<version>${javax.jacc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.seam</groupId>
<artifactId>jboss-seam</artifactId>
<version>${jboss.seam.version}</version>
<scope>provided</scope>
</dependency>

<!--
Time and Date
-->
Expand Down