Re: Seam, SAML, JAAS: How do I map IDP to an application user?
jonananas Sep 23, 2010 11:18 AMThanks for your reply, and you're right, that makes me comfortable, at least more so
Some notes:
I don't really need the actual user, I just need to know the organisation, and I am assuming that it's safe to use the IDP-id (set in external-authentication-config.xml).
Also I'm probably implementing IDP-discovery fairly easily, either by mapping the incoming ip (most or all organisations use a proxy with a short ip-range) or by providing a custom entrypoint for each organisation.
Your suggestion above was very insightful, to use JPA to lookup the user directly. That seems more straightforward than what I was about to do; to override the Credentials with a IDPCredentials and create a custom IDPToLocalUserLoginModule that would handle the mapping between IDP and user.
However, I still have the problem that after finding my user using JPA I would like to create a corresponding principal to be used by identity. I tried to do this using identity.getSubject.addPrincipal(), but realized that identity.acceptExternallyAuthenticatedPrincipal(Principal principal) sets identity.principal to the SAMLPrincipal. I don't want that since the principal.name is base for further authorization. If that's a bad idea I guess I could work around it by creating a session-scoped user-object that would override the identity.principal. I would prefer not to though.
I just tried creating my own org.picketlink.identity.seam.federation.internalAuthenticator by simply removing the identity.acceptExternallyAuthenticatedPrincipal(Principal principal) call, which seem to work with the InternalAuthenticator above. Is there a better way? If not using identity.login, how do I set the principal? (Or are you suggesting I shouldn't?)
Again, thank you.
-- Jonas
{code}
package com.metria.fsok.web.sso;
import java.security.Principal;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Import;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;
import org.picketlink.identity.seam.federation.configuration.ServiceProvider;
/**
* @author Marcel Kolsteren
* @since Jan 30, 2010
*/
@Name("org.picketlink.identity.seam.federation.internalAuthenticator")
@AutoCreate
@Install(precedence = Install.DEPLOYMENT + 10)
@Import("org.picketlink.identity.seam.federation")
public class PicketLinkInternalAuthenticator extends org.picketlink.identity.seam.federation.InternalAuthenticator {
@In
private Identity identity;
@In
private ServiceProvider serviceProvider;
@Logger
Log log;
@Override
public boolean authenticate(Principal principal, HttpServletRequest httpRequest) {
List<String> roles = new LinkedList<String>();
Boolean internallyAuthenticated = serviceProvider.getInternalAuthenticationMethod().invoke(principal, roles);
log.debug("Authenticated= " + internallyAuthenticated + " as " + identity.getPrincipal().getName());
if (internallyAuthenticated) {
// Removed to keep current principal
// identity.acceptExternallyAuthenticatedPrincipal(principal);
for (String role : roles) {
identity.addRole(role);
}
}
log.debug("Authenticated= " + internallyAuthenticated + " as " + identity.getPrincipal().getName());
return internallyAuthenticated;
}
}
{code}