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.util.EntityUtils; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.AuthorizationError; import org.openslx.bwlp.thrift.iface.TAuthorizationException; import org.openslx.dozmod.Branding; import org.openslx.dozmod.util.ProxyConfigurator; 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 service registration */ private static URL registrationUrl = null; /** * Return codes */ public static enum ReturnCode { // TODO rework this... NO_ERROR(0, "Authentication against the identity provider and request of the service provider resource worked."), IDENTITY_PROVIDER_ERROR(1, "Authentication against the identity provider failed."), UNREGISTERED_ERROR(2, "User not registered to use " + Branding.getServiceName() + "."), SERVICE_PROVIDER_ERROR(3, "Invalid resource of the service provider."), INVALID_URL_ERROR(4, "Invalid URL received from master server."), GENERIC_ERROR(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. */ public final static URI BWLP_SP; static { URI tmp; try { tmp = new URI("https://" + Branding.getMasterServerAddress() + "/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 TAuthorizationException */ public static ReturnCode doLogin(final String idpUrl, final String user, final String pass) throws TAuthorizationException, 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.GENERIC_ERROR; } if (idpUrl == null) { LOGGER.error("Identity provider is not set, did you initialize this class correctly?"); return ReturnCode.GENERIC_ERROR; } if (user == null) { LOGGER.error("No username given, aborting..."); return ReturnCode.GENERIC_ERROR; } if (pass == null) { LOGGER.error("No password given, aborting..."); return ReturnCode.GENERIC_ERROR; } // now init the authenticator for that idp and our static sp final ECPAuthenticator auth = new ECPAuthenticator(ProxyConfigurator.getClient(), user, pass, new URI(idpUrl), BWLP_SP); HttpResponse spResponse; try { spResponse = auth.authenticate(); } catch (ECPAuthenticationException e) { LOGGER.error("ECP Authentication Exception, see trace: ", e); throw new TAuthorizationException(AuthorizationError.GENERIC_ERROR, e.getMessage()); } if (spResponse.getStatusLine().getStatusCode() != 200) { LOGGER.error("SP does not return HTTP status code 200"); throw new TAuthorizationException(AuthorizationError.GENERIC_ERROR, "SP says: " + spResponse.getStatusLine().toString()); } LOGGER.debug("Login complete, getting body"); final String responseBody = EntityUtils.toString(spResponse.getEntity()); try { lastResponse = GSON.fromJson(responseBody, ServiceProviderResponse.class); } catch (JsonSyntaxException e) { LOGGER.warn("Json data from Service Provider malformed", e); LOGGER.warn("Response was:\n" + responseBody); throw e; } // 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.UNREGISTERED_ERROR; } // TODO the rest of the cases... if (lastResponse.status.equals("error")) { LOGGER.error("Server side error: " + lastResponse.error); return ReturnCode.GENERIC_ERROR; } if (lastResponse.status.equals("anonymous")) { LOGGER.error("IdP did not forward user account information to SP. Contact developer."); lastResponse.error = "Ihr Identity-Provider hat dem " + Branding.getServiceName() + "-System Ihre E-Mail oder Ihren Namen nicht mitgeteilt"; return ReturnCode.GENERIC_ERROR; } if (lastResponse.status.equals("ok")) { return ReturnCode.NO_ERROR; } // still here? then something else went wrong return ReturnCode.GENERIC_ERROR; } /** * @return Registration URL given by the SP. */ public static URL getRegistrationUrl() { return registrationUrl; } }