package org.openslx.dozmod.authentication;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.openslx.bwlp.thrift.iface.AuthenticationError;
import org.openslx.bwlp.thrift.iface.TAuthenticationException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import edu.kit.scc.dei.ecplean.ECPAuthenticationException;
import edu.kit.scc.dei.ecplean.ECPAuthenticator;
public class ShibbolethECP {
/**
* Logger instance for this class
*/
private final static Logger LOGGER = Logger.getLogger(ShibbolethECP.class);
/**
* Static gson object for (de)serialization
*/
private static final Gson GSON = new GsonBuilder().create();
/**
* ServiceProviderResponse Object representing the last response we received
*/
private static ServiceProviderResponse lastResponse = null;
/**
* URL for bwLehrpool registration
*/
private static URL registrationUrl = null;
/**
* Return codes
*/
public static enum ReturnCode {
NO_ERROR(0, "Authentication against the identity provider and request of the service provider resource worked."),
IDP_ERROR(1, "Authentication against the identity provider failed."),
UNREG_ERROR(2, "User not registered to use bwLehrpool."),
ERROR_SP(3, "Invalid resource of the service provider."),
ERROR_URL(4, "Invalid URL received from master server."),
ERROR_OTHER(5, "Internal error.");
private final int id;
private final String msg;
ReturnCode(int id, String msg) {
this.id = id;
this.msg = msg;
}
public int getId() {
return this.id;
}
public String getMsg() {
return this.msg;
}
}
/**
* Static URI to the SP.
*/
private final static URI BWLP_SP;
static {
URI tmp;
try {
tmp = new URI("https://bwlp-masterserver.ruf.uni-freiburg.de/webif/shib/api.php");
} catch (URISyntaxException e) {
// should never happen!
LOGGER.error("Bad URI syntax of the service provider, see trace: ", e);
tmp = null;
}
BWLP_SP = tmp;
}
public static ServiceProviderResponse getResponse() {
return lastResponse;
}
/**
* Fetches the resource
*
* @param idpUrl
* URL of the identity provider to authenticate against, as String.
* @param user
* Username as String.
* @param pass
* Password as String.
* @return
* true if login worked, false otherwise.
* @throws TAuthenticationException
*/
public static ReturnCode doLogin(final String idpUrl, final String user, final String pass)
throws TAuthenticationException, URISyntaxException, ClientProtocolException, IOException,
ParseException, JsonSyntaxException, MalformedURLException {
// first lets do some sanity checks
if (BWLP_SP == null) {
LOGGER.error("URI to service provider is not set. Check the initialization of 'BWLP_SP'.");
return ReturnCode.ERROR_OTHER;
}
if (idpUrl == null) {
LOGGER.error("Identity provider is not set, did you initialize this class correctly?");
return ReturnCode.ERROR_OTHER;
}
if (user == null) {
LOGGER.error("No username given, aborting...");
return ReturnCode.ERROR_OTHER;
}
if (pass == null) {
LOGGER.error("No password given, aborting...");
return ReturnCode.ERROR_OTHER;
}
// now init the authenticator for that idp and our static sp
final ECPAuthenticator auth = new ECPAuthenticator(user, pass, new URI(idpUrl), BWLP_SP);
try {
auth.authenticate();
} catch (ECPAuthenticationException e) {
LOGGER.error("ECP Authentication Exception, see trace: ", e);
throw new TAuthenticationException(AuthenticationError.GENERIC_ERROR, e.getMessage());
}
// here test again for the SP's URL
final HttpGet testSp = new HttpGet(BWLP_SP);
final HttpResponse response = auth.getHttpClient().execute(testSp);
LOGGER.debug("SP request returned: " + response.getStatusLine());
final String responseBody = EntityUtils.toString(response.getEntity());
lastResponse = GSON.fromJson(responseBody, ServiceProviderResponse.class);
// TODO: here we will need to parse the answer accordingly.
// no errors, meaning everything worked fine.
if (lastResponse.status.equals("unregistered")) {
registrationUrl = new URL(lastResponse.url);
return ReturnCode.UNREG_ERROR;
}
// TODO the rest of the cases...
if (lastResponse.status.equals("error")) {
LOGGER.error("Server side error: " + lastResponse.error);
return ReturnCode.ERROR_OTHER;
}
if (lastResponse.status.equals("anonymous")) {
LOGGER.error("IdP did not forward user account information to SP. Contact developper.");
return ReturnCode.ERROR_OTHER;
}
if (lastResponse.status.equals("ok")) {
return ReturnCode.NO_ERROR;
}
// still here? then something else went wrong
return ReturnCode.ERROR_OTHER;
}
/**
* @return Registration URL given by the SP.
*/
public static URL getRegistrationUrl() {
return registrationUrl;
}
}