org.asimba.auth.smsotp.distributor.mollie.MollieOTPDistributor.java Source code

Java tutorial

Introduction

Here is the source code for org.asimba.auth.smsotp.distributor.mollie.MollieOTPDistributor.java

Source

/*
 * Asimba Server
 * 
 * Copyright (C) 2012 Asimba
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see www.gnu.org/licenses
 * 
 * Asimba - Serious Open Source SSO - More information on www.asimba.org
 * 
 */
package org.asimba.auth.smsotp.distributor.mollie;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.asimba.auth.smsotp.OTP;
import org.asimba.auth.smsotp.distributor.IOTPDistributor;
import org.asimba.auth.smsotp.distributor.OTPDistributorException;
import org.w3c.dom.Element;

import com.alfaariss.oa.OAException;
import com.alfaariss.oa.SystemErrors;
import com.alfaariss.oa.api.attribute.IAttributes;
import com.alfaariss.oa.api.configuration.IConfigurationManager;
import com.alfaariss.oa.api.user.IUser;
import com.alfaariss.oa.engine.core.Engine;

public class MollieOTPDistributor implements IOTPDistributor {
    protected IConfigurationManager _oConfigurationManager;
    private static Logger _oLogger = Logger.getLogger(MollieOTPDistributor.class);

    /**
     * Configurable URL of the Mollie service
     */
    protected String _sUrl;
    protected URL _oURL;

    /**
     * Username and Password to authenticate to Mollie service
     */
    private String _sUsername;
    private String _sPassword;

    /**
     * Configurable sender-name of the SMS message
     */
    protected String _sSenderName;

    /**
     * The user attribute that contains the phonenr to send the 
     *   SMS message to
     */
    protected String _sPhonenrAttribute;

    /**
     * Message template that is used to format the OTP
     * This is text, with the special code ':1' replaced by the password
     */
    protected String _sMessageTemplate;

    private boolean _bStarted;

    public MollieOTPDistributor() {
        _bStarted = false;
    }

    /**
     * Distribute the OTP to the user<br/>
     * Requires a configured attribute to be present in the User's Attributes()-collection to
     * establish the phonenr to send the OneTimePassword to!<br/>
     * Updates Otp-instance to reflect the result of distributing the password (timessent, timesent)
     * 
     * Sources inspired by A-Select SMS AuthSP
     */
    public int distribute(OTP oOtp, IUser oUser) throws OAException, OTPDistributorException {
        // Are we operational?
        if (!_bStarted) {
            throw new OAException(SystemErrors.ERROR_NOT_INITIALIZED);
        }

        String sMsg;
        String sRecipient;
        IAttributes oUserAttributes;
        int returncode = 15;

        // Establish the phonenr to send message to
        oUserAttributes = oUser.getAttributes();
        if (!oUserAttributes.contains(_sPhonenrAttribute)) {
            _oLogger.error("Unknown phonenr for user " + oUser.getID() + "; missing attribute '"
                    + _sPhonenrAttribute + "'");
            throw new OTPDistributorException(returncode);
        }

        sRecipient = (String) oUserAttributes.get(_sPhonenrAttribute);

        // Establish message
        sMsg = getMessageForPwd(oOtp.getValue());

        // Establish URL
        StringBuffer sbData = new StringBuffer();

        try {
            ArrayList<String> params = new ArrayList<String>();

            // Depend on Apache Commons Lang for join
            params.add(StringUtils.join(new String[] { "gebruikersnaam", URLEncoder.encode(_sUsername, "UTF-8") },
                    "="));

            params.add(
                    StringUtils.join(new String[] { "wachtwoord", URLEncoder.encode(_sPassword, "UTF-8") }, "="));

            params.add(
                    StringUtils.join(new String[] { "afzender", URLEncoder.encode(_sSenderName, "UTF-8") }, "="));

            params.add(StringUtils.join(new String[] { "bericht", URLEncoder.encode(sMsg, "UTF-8") }, "="));

            params.add(
                    StringUtils.join(new String[] { "ontvangers", URLEncoder.encode(sRecipient, "UTF-8") }, "="));

            String sCGIString = StringUtils.join(params, "&");

            returncode++; // 16

            URLConnection oURLConnection = _oURL.openConnection();
            returncode++; // 17

            oURLConnection.setDoOutput(true);

            OutputStreamWriter oWriter = new OutputStreamWriter(oURLConnection.getOutputStream());
            oWriter.write(sCGIString);
            oWriter.flush();
            returncode++; // 18

            // Get the response
            BufferedReader oReader = new BufferedReader(new InputStreamReader(oURLConnection.getInputStream()));
            String sLine;

            if ((sLine = oReader.readLine()) != null) {
                returncode = Integer.parseInt(sLine);
            }

            if (returncode != 0) {
                _oLogger.error("Mollie could not send sms, returncode from Mollie: " + returncode + ".");
                throw new OTPDistributorException(returncode);
            }

            returncode++; // 19
            oWriter.close();
            oReader.close();
        } catch (NumberFormatException e) {
            _oLogger.error("Sending SMS, using \'" + _oURL.toString() + ", data=" + sbData.toString()
                    + "\' failed due to number format exception!" + e.getMessage());
            throw new OTPDistributorException(returncode);
        }

        catch (Exception e) {
            _oLogger.error("Sending SMS, using \'" + _oURL.toString() + ", data=" + sbData.toString()
                    + "\' failed (return code=" + returncode + ")! " + e.getMessage());
            throw new OTPDistributorException(returncode);
        }

        _oLogger.info("Sending to user " + oUser.getID() + " password with value " + oOtp.getValue());

        oOtp.registerSent(Long.valueOf(System.currentTimeMillis()));

        return returncode;
    }

    /**
     * Override this implementation to provide for localization support etc.
     * @param sPassword Password value to include in the message
     * @return Formatted message to sent to user.
     */
    protected String getMessageForPwd(String sPassword) {
        return _sMessageTemplate.replaceAll(":1", sPassword);
    }

    /**
     * Initialize MollieOtpDistributoir from configuration. Valid configuration can contain:<br/>
     * <url>urlvalue</url> (required) the Mollie URL to send SMS request to<br/>
     * <username>string</username> (required) name of the useraccount at Mollie<br/>
     * <password>string</password> (required) password of the useraccount at Mollie<br/>
     * <originator>string</originator> (optional) name of the originator of the SMS message; defaults to server@id<br/>
     * <phonenrattribute>string</phonenrattribute> (required) name of the user attribute that contains the phonenr to send the SMS to the user to<br/>
     */
    public void start(IConfigurationManager oConfigurationManager, Element eConfig) throws OAException {
        if ((eConfig == null) || (oConfigurationManager == null)) {
            _oLogger.error("No configuration supplied");
            throw new OAException(SystemErrors.ERROR_CONFIG_READ);
        }

        _oConfigurationManager = oConfigurationManager;

        _sUrl = _oConfigurationManager.getParam(eConfig, "url");
        if (_sUrl == null) {
            _oLogger.error("No 'url' element found in 'MollieOtpDistributor");
            throw new OAException(SystemErrors.ERROR_CONFIG_READ);
        }

        try {
            _oURL = new URL(_sUrl);
        } catch (MalformedURLException mue) {
            _oLogger.fatal("Invalid URL configured for MollieOtpDistributor'");
            throw new OAException(SystemErrors.ERROR_INIT);
        }

        _sUsername = _oConfigurationManager.getParam(eConfig, "username");
        if ((_sUsername == null) || _sUsername.equals("")) {
            _oLogger.error("No 'username' element found in 'MollieOtpDistributor'");
            throw new OAException(SystemErrors.ERROR_CONFIG_READ);
        }

        _sPassword = _oConfigurationManager.getParam(eConfig, "password");
        if ((_sPassword == null) || _sPassword.equals("")) {
            _oLogger.error("No 'password' element found in 'MollieOtpDistributor'");
            throw new OAException(SystemErrors.ERROR_CONFIG_READ);
        }

        _sSenderName = _oConfigurationManager.getParam(eConfig, "originator");
        if ((_sSenderName == null) || _sSenderName.equals("")) {
            _oLogger.debug("No 'originator' element found in 'MollieOtpDistributor', using defaults");

            // Default to the ID of the server
            _sSenderName = Engine.getInstance().getServer().getOrganization().getID();
        }

        _sPhonenrAttribute = _oConfigurationManager.getParam(eConfig, "phonenrattribute");
        if ((_sPhonenrAttribute == null) || _sPhonenrAttribute.equals("")) {
            _oLogger.error("No 'phonenrattribute' element found in 'MollieOtpDistributor'");
            throw new OAException(SystemErrors.ERROR_CONFIG_READ);
        }

        _sMessageTemplate = _oConfigurationManager.getParam(eConfig, "messagetemplate");
        if ((_sMessageTemplate == null) || _sMessageTemplate.equals("")) {
            _oLogger.debug("No 'messagetemplate' configured, using default");
            _sMessageTemplate = "Password is :1";
        }

        _bStarted = true;
    }

    public void stop() {
        _bStarted = false;
    }

}