package auth.impl;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.mvc.Http;
import play.mvc.Http.Context;
import auth.impl.callbackHandlers.HeadlessCallbackHandler;
import auth.impl.callbacks.HeadlessCallback;
import auth.impl.callbacks.HttpCookieCallback;
import auth.impl.callbacks.HttpRequestHeaderCallback;
import auth.impl.callbacks.OpenAMAttributesCallback;
import auth.models.User;
import auth.models.UserToken;
public class OpenAMAuthModule extends AbstractAuthModule {
private static Logger logger = LoggerFactory.getLogger(OpenAMAuthModule.class);
private static final String OPEN_AM_AUTH_MODULE = "OpenAMAuth";
private static final String OPEN_AM_PREFIX = "HTTP_";
private static final String USER_ID = "username";
private static final String USER_FULLNAME = "fullname";
private static final String USER_EMAIL = "email";
private static final String USER_PHONE = "phone";
private String userAttr;
private String fullNameAttr;
private String emailAttr;
private String phoneAttr;
private String openAmUrl;
/* (non-Javadoc)
* @see auth.IAuthModule#getCallbackHandler(play.mvc.Http.Context)
*/
@Override
public CallbackHandler getCallbackHandler(Context ctx) {
return new HeadlessCallbackHandler(ctx);
}
/* (non-Javadoc)
* @see auth.IAuthModule#getModuleName()
*/
@Override
public String getModuleName() {
return OPEN_AM_AUTH_MODULE;
}
/* (non-Javadoc)
* @see javax.security.auth.spi.LoginModule#login()
*/
@Override
public boolean login() throws LoginException {
logger.debug("login()");
if (callbackHandler == null) {
throw new LoginException("Error: no CallbackHandler available!");
}
ArrayList<Callback> callbacks = new ArrayList<Callback>();
callbacks.add(new HttpCookieCallback(userAttr));
callbacks.add(new HttpCookieCallback(fullNameAttr));
callbacks.add(new HttpCookieCallback(phoneAttr));
callbacks.add(new HttpCookieCallback(emailAttr));
callbacks.add(new HttpRequestHeaderCallback(userAttr));
callbacks.add(new HttpRequestHeaderCallback(fullNameAttr));
callbacks.add(new HttpRequestHeaderCallback(phoneAttr));
callbacks.add(new HttpRequestHeaderCallback(emailAttr));
try {
Callback[] cb = new Callback[callbacks.size()];
callbackHandler.handle(callbacks.toArray(cb));
Http.Context ctx = null;
Http.Request req = null;
String userid = null, fullname = null, email = null, phone = null;
for (int i=0; i<cb.length; i++) {
if (cb[i] instanceof HttpRequestHeaderCallback) {
HttpRequestHeaderCallback c = (HttpRequestHeaderCallback) cb[i];
if (c.getName().equals(userAttr) && c.getValue() != null) userid = c.getValue();
if (c.getName().equals(fullNameAttr) && c.getValue() != null) fullname = c.getValue();
if (c.getName().equals(emailAttr) && c.getValue() != null) email = c.getValue();
if (c.getName().equals(phoneAttr) && c.getValue() != null) phone = c.getValue();
} else if (cb[i] instanceof HttpCookieCallback) {
HttpCookieCallback c = (HttpCookieCallback) cb[i];
if (c.getName().equals(userAttr) && c.getValue() != null) userid = c.getValue();
if (c.getName().equals(fullNameAttr) && c.getValue() != null) fullname = c.getValue();
if (c.getName().equals(emailAttr) && c.getValue() != null) email = c.getValue();
if (c.getName().equals(phoneAttr) && c.getValue() != null) phone = c.getValue();
} else if (cb[i] instanceof OpenAMAttributesCallback) {
// do nothing
} else {
logger.info("Don't know how to work with callback: " + cb[i].getClass().getName());
}
if (cb[i] instanceof HeadlessCallback) {
ctx = ((HeadlessCallback)cb[i]).getOriginalContext();
req = ((HeadlessCallback)cb[i]).getOriginalRequest();
}
}
// TODO - try using REST API ...
if (userid == null && ctx != null) {
// if not found in HTTP request header or cookies, fall back to back channel call to OpenAM
logger.debug("nothing found in headers, try REST API ...");
ArrayList<String> lst = new ArrayList<String>();
lst.add("uid"); lst.add("cn"); lst.add("telephonenumber"); lst.add("mail");
OpenAMAttributesCallback amcb = new OpenAMAttributesCallback(openAmUrl, lst);
amcb.process(ctx);
userid = amcb.getValue("uid");
if (fullname == null) fullname = amcb.getValue("cn");
if (phone == null) phone = amcb.getValue("telephonenumber");
if (email == null) email = amcb.getValue("mail");
}
pending = new ArrayList<Principal>();
if (userid != null) {
User user = UserToken.createUserToken(userid, "cangetin", req);
user.fullName = fullname;
//user.email = email; user.phone = phone;
pending.add(user);
return true;
}
} catch (Exception e) {
logger.info("failed user validation.", e);
}
return false;
}
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
Map<String, ?> options) {
super.initialize(subject, callbackHandler, sharedState, options);
userAttr = getOption("userAttr", null);
if (userAttr == null) {
userAttr = USER_ID;
logger.debug("userAttr not configured; using default: " + userAttr);
}
userAttr = OPEN_AM_PREFIX + userAttr;
fullNameAttr = getOption("fullNameAttr", null);
if (fullNameAttr == null) {
fullNameAttr = USER_FULLNAME;
logger.debug("fullNameAttr not configured; using default: " + fullNameAttr);
}
fullNameAttr = OPEN_AM_PREFIX + fullNameAttr;
emailAttr = getOption("emailAttr", null);
if (emailAttr == null) {
emailAttr = USER_EMAIL;
logger.debug("emailAttr not configured; using default: " + emailAttr);
}
emailAttr = OPEN_AM_PREFIX + emailAttr;
phoneAttr = getOption("phoneAttr", null);
if (phoneAttr == null) {
phoneAttr = USER_PHONE;
logger.debug("phoneAttr not configured; using default: " + phoneAttr);
}
phoneAttr = OPEN_AM_PREFIX + phoneAttr;
openAmUrl = getOption("openAmUrl", null);
if (openAmUrl == null) {
logger.debug("openAmUrl not configured");
}
}
}