view gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Response.java @ 9497:d6d5ca6d4af0

Enabled logging of saml-group-name in log-ing logfile. Some cleanup/refaktoring.
author gernotbelger
date Thu, 27 Sep 2018 17:40:39 +0200
parents 5e38e2924c07
children
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.client.server.auth.was;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringBufferInputStream;
import java.util.List;

import org.apache.commons.codec.binary.Base64InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.dive4elements.artifacts.httpclient.utils.XMLUtils;
import org.dive4elements.river.client.server.auth.Authentication;
import org.dive4elements.river.client.server.auth.AuthenticationException;
import org.dive4elements.river.client.server.auth.DefaultUser;
import org.dive4elements.river.client.server.auth.User;
import org.dive4elements.river.client.server.auth.saml.Assertion;
import org.dive4elements.river.client.server.auth.saml.TicketValidator;
import org.dive4elements.river.client.server.auth.saml.XPathUtils;
import org.dive4elements.river.client.server.features.Features;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Response implements Authentication {

    private static Logger log = Logger.getLogger(Response.class);

    private final Element root;
    private final String samlTicketXML;
    private Assertion assertion;
    private final String password;
    private final Features features;
    private final String trustedKeyFile;
    private final String timeEpsilon;

    public Response(final HttpEntity entity, final String password, final Features features, final String trustedKeyFile,
            final String timeEpsilon) throws AuthenticationException, IOException {

        if (entity == null) {
            throw new ServiceException("Invalid response");
        }

        final String contenttype = entity.getContentType().getValue();
        final String samlTicketXML = EntityUtils.toString(entity);

        InputStream in = new StringBufferInputStream(samlTicketXML);

        if (!contenttype.equals("application/vnd.ogc.se_xml")) {
            // XXX: Assume base64 encoded content.
            in = new Base64InputStream(in);
        }

        final Document doc = XMLUtils.readDocument(in);
        final Element root = doc.getDocumentElement();
        final String rname = root.getTagName();

        if (rname != null && rname.equals("ServiceExceptionReport"))
            throw new ServiceException(XPathUtils.xpathString(root, "ServiceException"));

        this.samlTicketXML = samlTicketXML;
        this.root = root;
        this.password = password;
        this.features = features;
        this.trustedKeyFile = trustedKeyFile;
        this.timeEpsilon = timeEpsilon;
    }

    @Override
    public boolean isSuccess() {
        final String status = getStatus();
        return status != null && status.equals("samlp:Success");
    }

    private String getStatus() {
        return XPathUtils.xpathString(this.root, "./samlp:Status/samlp:StatusCode/@Value");
    }

    private Assertion getAssertion() {
        if (this.assertion == null && this.root != null) {
            try {
                final int timeEps = Integer.parseInt(this.timeEpsilon);
                final TicketValidator validator = new TicketValidator(this.trustedKeyFile, timeEps);
                this.assertion = validator.checkTicket(this.root);
            }
            catch (final Exception e) {
                log.error(e.getLocalizedMessage(), e);
            }
        }
        return this.assertion;
    }

    @Override
    public User getUser() throws AuthenticationException {
        final Assertion assertion = this.getAssertion();
        if (assertion == null)
            throw new AuthenticationException("Response doesn't contain an assertion");

        final DefaultUser user = createUser(this.password, this.samlTicketXML, assertion, this.features);

        log.debug("User " + user.getName() + " with features " + user.getAllowedFeatures() + " successfully authenticated.");

        return user;
    }

    public static DefaultUser createUser(final String password, final String samlTicketXML, final Assertion assertion, final Features features) {
        final List<String> roles = assertion.getRoles();

        final List<String> allowedFeatures = features.getFeatures(roles);

        // We could check the validity dates of the assertion here, but
        // when using this for Single-Sign-On this would lead to the
        // code in GGInAFilter to re-authenticate with the password
        // stored in the User object, which isn't known in the case of
        // Single-Sign-On.
        final boolean expired = false;

        final String username = assertion.getNameID();
        final String userGroup = assertion.getGroupName();

        return new DefaultUser(username, password, samlTicketXML, expired, roles, allowedFeatures, userGroup);
    }
}

http://dive4elements.wald.intevation.org