diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/AuthorityGranter.java b/core/src/main/java/org/acegisecurity/providers/jaas/AuthorityGranter.java
new file mode 100644
index 0000000000..155b278cf4
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/AuthorityGranter.java
@@ -0,0 +1,13 @@
+package net.sf.acegisecurity.providers.jaas;
+
+import java.security.Principal;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public interface AuthorityGranter {
+ public String grant(Principal principal);
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JAASAuthenticationCallbackHandler.java b/core/src/main/java/org/acegisecurity/providers/jaas/JAASAuthenticationCallbackHandler.java
new file mode 100644
index 0000000000..4a9c40e48c
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/JAASAuthenticationCallbackHandler.java
@@ -0,0 +1,20 @@
+package net.sf.acegisecurity.providers.jaas;
+
+import net.sf.acegisecurity.Authentication;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public interface JAASAuthenticationCallbackHandler {
+ void setAuthentication(Authentication auth);
+ void handle(Callback callback) throws IOException, UnsupportedCallbackException;
+
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JAASAuthenticationProvider.java b/core/src/main/java/org/acegisecurity/providers/jaas/JAASAuthenticationProvider.java
new file mode 100644
index 0000000000..e852541b69
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/JAASAuthenticationProvider.java
@@ -0,0 +1,166 @@
+package net.sf.acegisecurity.providers.jaas;
+
+import net.sf.acegisecurity.providers.jaas.event.JAASAuthenticationFailedEvent;
+import net.sf.acegisecurity.providers.jaas.event.JAASAuthenticationSuccessEvent;
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.AuthenticationException;
+import net.sf.acegisecurity.AuthenticationServiceException;
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.providers.AuthenticationProvider;
+import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+import net.sf.acegisecurity.providers.jaas.AuthorityGranter;
+import net.sf.acegisecurity.providers.jaas.JAASAuthenticationCallbackHandler;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationContextException;
+import org.springframework.core.io.Resource;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import java.io.IOException;
+import java.security.Principal;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public class JAASAuthenticationProvider implements AuthenticationProvider, InitializingBean, ApplicationContextAware {
+
+ private ApplicationContext context;
+ private String loginContextName = "ACEGI";
+ private Resource loginConfig;
+ private JAASAuthenticationCallbackHandler[] callbackHandlers;
+ private AuthorityGranter[] authorityGranters;
+
+ public Authentication authenticate(Authentication auth) throws AuthenticationException {
+ if (auth instanceof UsernamePasswordAuthenticationToken) {
+ UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) auth;
+
+ try {
+
+ LoginContext lc = new LoginContext(loginContextName, new InternalCallbackHandler(auth));
+ lc.login();
+
+ Set authorities = new HashSet();
+
+ if (token.getAuthorities() != null) {
+ authorities.addAll(Arrays.asList(token.getAuthorities()));
+ }
+
+ Subject subject = lc.getSubject();
+
+
+ Set principals = subject.getPrincipals();
+ for (Iterator iterator = principals.iterator(); iterator.hasNext();) {
+ Principal principal = (Principal) iterator.next();
+ for (int i = 0; i < authorityGranters.length; i++) {
+ AuthorityGranter granter = authorityGranters[i];
+ String role = granter.grant(principal);
+ if (role != null) {
+ authorities.add(new JAASGrantedAuthority(role, principal));
+ }
+ }
+ }
+
+ token.setAuthorities((GrantedAuthority[]) authorities.toArray(new GrantedAuthority[authorities.size()]));
+
+ context.publishEvent(new JAASAuthenticationSuccessEvent(token));
+
+ return token;
+
+ } catch (LoginException e) {
+ context.publishEvent(new JAASAuthenticationFailedEvent(auth, e));
+ throw new AuthenticationServiceException(e.toString());
+ }
+ }
+ return null;
+ }
+
+ public boolean supports(Class aClass) {
+ return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.context = applicationContext;
+ }
+
+ public String getLoginContextName() {
+ return loginContextName;
+ }
+
+ public void setLoginContextName(String loginContextName) {
+ this.loginContextName = loginContextName;
+ }
+
+ public Resource getLoginConfig() {
+ return loginConfig;
+ }
+
+ public void setLoginConfig(Resource loginConfig) throws IOException {
+ this.loginConfig = loginConfig;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+
+ if (loginConfig == null)
+ throw new ApplicationContextException("loginConfig must be set on " + getClass());
+
+ if (loginContextName == null)
+ throw new ApplicationContextException("loginContextName must be set on " + getClass());
+
+ int n = 1;
+ while (Security.getProperty("login.config.url." + n) != null) n++;
+
+ Security.setProperty("login.config.url." + n, loginConfig.getURL().toString());
+ }
+
+ public JAASAuthenticationCallbackHandler[] getCallbackHandlers() {
+ return callbackHandlers;
+ }
+
+ public void setCallbackHandlers(JAASAuthenticationCallbackHandler[] callbackHandlers) {
+ this.callbackHandlers = callbackHandlers;
+ }
+
+ public AuthorityGranter[] getAuthorityGranters() {
+ return authorityGranters;
+ }
+
+ public void setAuthorityGranters(AuthorityGranter[] authorityGranters) {
+ this.authorityGranters = authorityGranters;
+ }
+
+ private class InternalCallbackHandler implements CallbackHandler {
+
+ private Authentication authentication;
+
+ public InternalCallbackHandler(Authentication authentication) {
+ this.authentication = authentication;
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+
+ for (int i = 0; i < callbackHandlers.length; i++) {
+ JAASAuthenticationCallbackHandler handler = callbackHandlers[i];
+ handler.setAuthentication(authentication);
+ for (int j = 0; j < callbacks.length; j++) {
+ Callback callback = callbacks[j];
+ handler.handle(callback);
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JAASGrantedAuthority.java b/core/src/main/java/org/acegisecurity/providers/jaas/JAASGrantedAuthority.java
new file mode 100644
index 0000000000..e66f0a538b
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/JAASGrantedAuthority.java
@@ -0,0 +1,25 @@
+package net.sf.acegisecurity.providers.jaas;
+
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+
+import java.security.Principal;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public class JAASGrantedAuthority extends GrantedAuthorityImpl {
+
+ Principal principal;
+
+ public JAASGrantedAuthority(String role, Principal principal) {
+ super(role);
+ this.principal = principal;
+ }
+
+ public Principal getPrincipal() {
+ return principal;
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JAASNameCallbackHandler.java b/core/src/main/java/org/acegisecurity/providers/jaas/JAASNameCallbackHandler.java
new file mode 100644
index 0000000000..2f179e3ad3
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/JAASNameCallbackHandler.java
@@ -0,0 +1,31 @@
+package net.sf.acegisecurity.providers.jaas;
+
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.providers.jaas.JAASAuthenticationCallbackHandler;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public class JAASNameCallbackHandler implements JAASAuthenticationCallbackHandler {
+
+ private Authentication authentication;
+
+ public void setAuthentication(Authentication authentication) {
+ this.authentication = authentication;
+ }
+
+ public void handle(Callback callback) throws IOException, UnsupportedCallbackException {
+ if (callback instanceof NameCallback) {
+ NameCallback ncb = (NameCallback) callback;
+ ncb.setName(authentication.getPrincipal().toString());
+ }
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/JAASPasswordCallbackHandler.java b/core/src/main/java/org/acegisecurity/providers/jaas/JAASPasswordCallbackHandler.java
new file mode 100644
index 0000000000..1e683bdda9
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/JAASPasswordCallbackHandler.java
@@ -0,0 +1,31 @@
+package net.sf.acegisecurity.providers.jaas;
+
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.providers.jaas.JAASAuthenticationCallbackHandler;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public class JAASPasswordCallbackHandler implements JAASAuthenticationCallbackHandler {
+
+ private Authentication auth;
+
+ public void setAuthentication(Authentication auth) {
+ this.auth = auth;
+ }
+
+ public void handle(Callback callback) throws IOException, UnsupportedCallbackException {
+ if (callback instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) callback;
+ pc.setPassword(auth.getCredentials().toString().toCharArray());
+ }
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationEvent.java b/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationEvent.java
new file mode 100644
index 0000000000..d562a23cbf
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationEvent.java
@@ -0,0 +1,21 @@
+package net.sf.acegisecurity.providers.jaas.event;
+
+import net.sf.acegisecurity.Authentication;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public abstract class JAASAuthenticationEvent extends ApplicationEvent {
+
+ public JAASAuthenticationEvent(Authentication auth) {
+ super(auth);
+ }
+
+ public Authentication getAuthentication() {
+ return (Authentication) source;
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationFailedEvent.java b/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationFailedEvent.java
new file mode 100644
index 0000000000..4d031ceb01
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationFailedEvent.java
@@ -0,0 +1,25 @@
+package net.sf.acegisecurity.providers.jaas.event;
+
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.providers.jaas.event.JAASAuthenticationEvent;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public class JAASAuthenticationFailedEvent extends JAASAuthenticationEvent {
+
+ private Exception exception;
+
+ public JAASAuthenticationFailedEvent(Authentication auth, Exception exception) {
+ super(auth);
+ this.exception = exception;
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+
+}
diff --git a/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationSuccessEvent.java b/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationSuccessEvent.java
new file mode 100644
index 0000000000..589bfd09a7
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/providers/jaas/event/JAASAuthenticationSuccessEvent.java
@@ -0,0 +1,18 @@
+package net.sf.acegisecurity.providers.jaas.event;
+
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.providers.jaas.event.JAASAuthenticationEvent;
+
+/**
+ * Insert comments here...
+ *
+ * User: raykrueger@users.sourceforge.net
+ * Date: Jul 15, 2004
+ */
+public class JAASAuthenticationSuccessEvent extends JAASAuthenticationEvent {
+
+ public JAASAuthenticationSuccessEvent(Authentication auth) {
+ super(auth);
+ }
+
+}