package net.vinant.idp4java.openid4javaImpl;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.vinant.idp4java.base.BaseAuthenticationHandler;
import net.vinant.idp4java.base.BaseProtocolImplementation;
import net.vinant.idp4java.base.BaseServiceProxy;
import net.vinant.idp4java.base.IUser;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openid4java.association.AssociationException;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.AuthSuccess;
import org.openid4java.message.DirectError;
import org.openid4java.message.Message;
import org.openid4java.message.MessageException;
import org.openid4java.message.MessageExtension;
import org.openid4java.message.Parameter;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
import org.openid4java.message.sreg.SRegMessage;
import org.openid4java.message.sreg.SRegRequest;
import org.openid4java.message.sreg.SRegResponse;
import org.openid4java.server.ServerException;
import org.openid4java.server.ServerManager;
public class OpenId4JavaProtocolImplementation extends
BaseProtocolImplementation {
private enum MODE {associate, checkid_setup, checkid_immediate, check_authentication};
private Log log = LogFactory.getLog(OpenId4JavaProtocolImplementation.class);
public OpenId4JavaProtocolImplementation(BaseServiceProxy proxy) {
super(proxy);
}
@Override
public String handle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
if(isAuthenticationRequest(request)){
BaseAuthenticationHandler authenticationHandler = ((SimpleServiceProxy)getServiceProxy()).getAuthenticationHandler();
Object u = request.getParameter("username");
Object p = request.getParameter("password");
String username = u!=null?(String)u:null;
String password = p!=null?(String)p:null;
IUser authorizedUser = authenticationHandler.authenticate(username, password);
if(authorizedUser == null){
//response.sendRedirect("login.jsp");
request.getRequestDispatcher("/login").forward(request, response);
return null;
}else{
if(session.getAttribute("parameterlist")!=null){
ParameterList requestp=(ParameterList) session.getAttribute("parameterlist");
String openidrealm=requestp.hasParameter("openid.realm") ? requestp.getParameterValue("openid.realm") : null;
String openidreturnto=requestp.hasParameter("openid.return_to") ? requestp.getParameterValue("openid.return_to") : null;
String openidclaimedid=requestp.hasParameter("openid.claimed_id") ? requestp.getParameterValue("openid.claimed_id") : null;
String openididentity=requestp.hasParameter("openid.identity") ? requestp.getParameterValue("openid.identity") : null;
session.setAttribute("openid.realm", openidrealm);
session.setAttribute("openid.return_to", openidreturnto);
session.setAttribute("openid.claimed_id", openidclaimedid );
session.setAttribute("openid.identity", openididentity);
session.setAttribute("authenticatedAndApproved", authorizedUser);
}
}
}
ServerManager manager = ((SimpleServiceProxy)getServiceProxy()).getServerManager();
// extract the parameters from the request
ParameterList parameterList = null;
if (session.getAttribute("parameterlist")!=null) {
parameterList = (ParameterList) session.getAttribute("parameterlist");
} else {
parameterList = new ParameterList(request.getParameterMap());
}
String mode = parameterList.hasParameter("openid.mode") ? parameterList.getParameterValue("openid.mode") : null;
log.debug("openid.mode:" + mode);
if(StringUtils.isEmpty(mode)){
//request.getRequestDispatcher("login.jsp").forward(request, response);
response.sendRedirect("/idp4java/login");
return null;
}
switch(MODE.valueOf(mode)){
case associate: return associate(request, response, parameterList);
case checkid_setup: return checkId(request, response, parameterList);
case checkid_immediate: return checkId(request, response, parameterList);
case check_authentication: return checkAuthentication(request, response, parameterList);
default: return unknownError(request, response, parameterList);
}
}
private boolean isAuthenticationRequest(HttpServletRequest request) {
if ("doLogin".equals(request.getParameter("action")))
return true;
return false;
}
private String unknownError(HttpServletRequest request, HttpServletResponse response, ParameterList parameterList) throws IOException {
Message messageResponse;
String responseText;
// --- error response ---
// When openid.mode = null or does not match any of the standard modes.
messageResponse = DirectError.createDirectError("Unknown request");
responseText = messageResponse.keyValueFormEncoding();
// return the result to the user
return directResponse(response,messageResponse.keyValueFormEncoding());
}
private String checkAuthentication(HttpServletRequest request, HttpServletResponse response, ParameterList parameterList) throws IOException {
ServerManager manager = ((SimpleServiceProxy)getServiceProxy()).getServerManager();
HttpSession session = request.getSession();
Message messageResponse;
String responseText;
// --- processing a verification request ---
messageResponse = manager.verify(parameterList);
responseText = messageResponse.keyValueFormEncoding();
return directResponse(response, messageResponse.keyValueFormEncoding());
}
private String checkId(HttpServletRequest request, HttpServletResponse response, ParameterList parameterList) throws ServletException, IOException {
ServerManager manager = ((SimpleServiceProxy)getServiceProxy()).getServerManager();
HttpSession session = request.getSession();
Message messageResponse;
String responseText;
// interact with the user and obtain data needed to continue
String userSelectedId = null;
String userSelectedClaimedId = null;
User authenticatedAndApproved = null;
String email = "";
if (session.getAttribute("authenticatedAndApproved") == null) {
session.setAttribute("parameterlist", parameterList);
String wwwParams = wwwFormEncoding(parameterList);
String url = "login.jsp?" + wwwParams;
response.sendRedirect(url);
return null;
} else {
userSelectedId = (String) session.getAttribute("openid.claimed_id");
userSelectedClaimedId = (String) session.getAttribute("openid.identity");
authenticatedAndApproved = (User) session.getAttribute("authenticatedAndApproved");
// Remove the parameterlist so this provider can accept requests from elsewhere
session.removeAttribute("parameterlist");
session.setAttribute("authenticatedAndApproved", null);
}
// --- process an authentication request ---
AuthRequest authReq = null;
String opLocalId = null;
try {
authReq = AuthRequest.createAuthRequest(parameterList, manager.getRealmVerifier());
// if the user chose a different claimed_id than the one in request
if (userSelectedClaimedId != null && userSelectedClaimedId.equals(authReq.getClaimed())) {
//opLocalId = "http://localhost:8081/idp4java/idp";//lookupLocalId(userSelectedClaimedId);
}
} catch (MessageException e) {
e.printStackTrace();
throw new ServletException(e);
}
// --- process an authentication request ---
//messageResponse = manager.authResponse(parameterList, userSelectedId, userSelectedClaimedId, true);
messageResponse = manager.authResponse(parameterList, opLocalId, opLocalId, true);
if (messageResponse instanceof DirectError)
return directResponse(response, messageResponse.keyValueFormEncoding());
else {
try {
if (authReq.hasExtension(AxMessage.OPENID_NS_AX))
{
MessageExtension ext = authReq.getExtension(AxMessage.OPENID_NS_AX);
if (ext instanceof FetchRequest)
{
FetchRequest fetchReq = (FetchRequest) ext;
Map required = fetchReq.getAttributes(true);
Map optional = fetchReq.getAttributes(false);
if (required.containsKey("email"))
{
Map userDataExt = new HashMap();
userDataExt.put("email", "someone@someplace.com");
FetchResponse fetchResp = FetchResponse.createFetchResponse(fetchReq, userDataExt);
// (alternatively) manually add attribute values
//fetchResp.addAttribute("email", "http://schema.openid.net/contact/email", email);
messageResponse.addExtension(fetchResp);
}
}
else //if (ext instanceof StoreRequest)
{
throw new UnsupportedOperationException("TODO");
}
}
if (authReq.hasExtension(SRegMessage.OPENID_NS_SREG))
{
MessageExtension ext = authReq.getExtension(SRegMessage.OPENID_NS_SREG);
if (ext instanceof SRegRequest)
{
SRegRequest sregReq = (SRegRequest) ext;
List required = sregReq.getAttributes(true);
List optional = sregReq.getAttributes(false);
if (required.contains("email"))
{
// data released by the user
Map userDataSReg = new HashMap();
userDataSReg.put("email", "user@example.com");
SRegResponse sregResp = SRegResponse.createSRegResponse(sregReq, userDataSReg);
// (alternatively) manually add attribute values
//sregResp.addAttribute("email", email);
messageResponse.addExtension(sregResp);
}
}
else
{
throw new UnsupportedOperationException("TODO");
}
}
// Sign the auth success message.
// This is required as AuthSuccess.buildSignedList has a `todo' tag now.
manager.sign((AuthSuccess) messageResponse);
} catch (MessageException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AssociationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// caller will need to decide which of the following to use:
// option1: GET HTTP-redirect to the return_to URL
session.setAttribute("SUCCESS", Boolean.TRUE);
response.sendRedirect(messageResponse.getDestinationUrl(true));
// option2: HTML FORM Redirection
//RequestDispatcher dispatcher =
// getServletContext().getRequestDispatcher("formredirection.jsp");
//httpReq.setAttribute("prameterMap", response.getParameterMap());
//httpReq.setAttribute("destinationUrl", response.getDestinationUrl(false));
//dispatcher.forward(request, response);
//return null;
return null;
}
}
private String associate(HttpServletRequest request, HttpServletResponse response, ParameterList parameterList) throws IOException {
ServerManager manager = ((SimpleServiceProxy)getServiceProxy()).getServerManager();
HttpSession session = request.getSession();
Message messageResponse;
String responseText;
// --- process an association parameterList ---
messageResponse = manager.associationResponse(parameterList);
responseText = messageResponse.keyValueFormEncoding();
return directResponse(response, messageResponse.keyValueFormEncoding());
}
private String directResponse(HttpServletResponse response, String messageResponse)
throws IOException
{
ServletOutputStream os = response.getOutputStream();
os.write(messageResponse.getBytes());
os.close();
return null;
}
private String wwwFormEncoding(ParameterList parameterList)
{
StringBuffer allParams = new StringBuffer("");
List parameters = parameterList.getParameters();
Iterator iterator = parameters.iterator();
while (iterator.hasNext())
{
Parameter parameter = (Parameter) iterator.next();
// All of the keys in the request message MUST be prefixed with "openid."
if ( ! parameter.getKey().startsWith("openid."))
allParams.append("openid.");
try
{
allParams.append(URLEncoder.encode(parameter.getKey(), "UTF-8"));
allParams.append('=');
allParams.append(URLEncoder.encode(parameter.getValue(), "UTF-8"));
allParams.append('&');
}
catch (UnsupportedEncodingException e)
{
return null;
}
}
// remove the trailing '&'
if (allParams.length() > 0)
allParams.deleteCharAt(allParams.length() -1);
return allParams.toString();
}
}