Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
package dk.portalprotect.nodb.plugins;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dk.itp.security.authentication.sms.SMSAuthenticationPlugin;
import dk.itp.security.passticket.PTException;
import dk.itp.security.passticket.User;
import dk.itp.security.passticket.server.AuthErrorCodes;

/**
 * Examplle authentication plugin, used to demonstrate authenticating using SMS. 
 *  
 * @author Kim Rasmussen
 *
 * <pre>
 * Ceptor - http://ceptor.io
 * Copyright(c) 2018, Asseco Denmark A/S, All rights reserved.
 * 
 * This source code is confidential.
 * </pre>
 */
public class SMSAuthenticationExample extends SMSAuthenticationPlugin {
	static Logger log = LoggerFactory.getLogger(SMSAuthenticationExample.class.getName());
	static final int DEFAULT_AUTHLEVEL = 10;

	/**
	 * @see dk.itp.security.authentication.IAuthenticationPlugin#getAuthenticationLevel()
	 */
	public int getAuthenticationLevel() {
		return DEFAULT_AUTHLEVEL;
	}

	/**
	 * @see dk.itp.security.authentication.IAuthenticationPlugin#login(User, String, Object, Object)
	 */
	public void login(User user, String userid, Object credentials) throws PTException {
		if (credentials instanceof String) {
			user.removeStateObject("SMS_OTP");
			user.removeStateObject("SMS_USERID");

			// Lookup userid in user repository, verify password
			// In this NON-PRODUCTION example, we assume the userid is the phone number, and the password is "password"

			if (!credentials.equals("password")) {
				throw new PTException("Invalid password", AuthErrorCodes.ERROR_INVALIDCREDENTIALS, "Invalid credentials");
			}

			// If we get here, the password is ok

			// For now, use the userid as phone number - in a real authentication plugin, look it up somewhere else.
			String mobile = userid;
			mobile = mobile == null ? "" : mobile.trim();

			if (mobile.startsWith("+"))
				mobile = mobile.substring(1);
			int ofs = mobile.indexOf(' ');
			while(ofs >= 0) {
				mobile = mobile.substring(0,ofs) + mobile.substring(ofs+1);
				ofs = mobile.indexOf(' ');
			}

			if (mobile == null || mobile.length() == 0)
				throw new PTException("No mobile number on record, cannot send PIN via SMS", AuthErrorCodes.ERROR_NOMOBILEPHONE, "No mobile number, cannot send SMS");

			// If 8 chars, assume danish and add country code 45 for Denmark
			if (mobile.length() == 8)
				mobile = "45"+mobile;

			// Generate an OTP, store it in the session, and throw an exception telling the application we need the OTP.
			String otp = generateOTP();

			user.setStateObject("SMS_OTP", otp);
			user.setStateObject("SMS_USERID", userid);

			try {
				if (!sendSMS(mobile, "PIN:\n"+otp))
					throw new PTException("Unable to send SMS to " + mobile, AuthErrorCodes.ERROR_NOMOBILEPHONE, "Problem with mobile, cannot send SMS");
			} catch (MalformedURLException e) {
				throw new PTException("Unable to send SMS to " + mobile, AuthErrorCodes.ERROR_NOMOBILEPHONE, "Configuration problem - invalid SMS configuration", e);
			} catch (IOException e) {
				throw new PTException("Unable to send SMS to " + mobile, AuthErrorCodes.ERROR_NOMOBILEPHONE, "Problem contacting SMS Gateway", e);
			}

			log.info("Logon with userid/password OK - SMS sent to " + mobile + ", need relogin with pincode");
			throw new PTException("Need OTP pincode", AuthErrorCodes.ERROR_NEED_OTP, "Need OTP code");

		} else if (credentials instanceof String[]) {
			// String[] means we are called with the one-time password.

			userid = (String) user.getStateObject("SMS_USERID");
			String otp = (String)user.getStateObject("SMS_OTP");

			if (userid == null || otp == null) {
				throw new PTException("Problem logging in, no userid present or timeout", AuthErrorCodes.ERROR_GENERALERROR, "No previous userid/password login or timeout");
			}

			// Remove allows only one try - keep it to allow multiple attempts at entering the correct PIN
			user.removeStateObject("SMS_OTP");
			user.removeStateObject("SMS_USERID");

			if (!((String[])credentials)[0].equalsIgnoreCase(otp)) {
				throw new PTException("Invalid OTP PIN", AuthErrorCodes.ERROR_INVALIDCREDENTIALS, "Invalid PIN code");
			}

			user.userid = userid;
			user.isLoggedOn = true;

			// Fill remaining information onto session
		}
		else {
			log.error("Cannot login, unsupported type of credentials");
			throw new PTException("Unsupported type of credentials - cannot login", AuthErrorCodes.ERROR_GENERALERROR, "Unsupported type of credentials");
		}
	}
	/**
	 * @see dk.itp.security.authentication.IAuthenticationPlugin#setConfiguration(Properties)
	 */
	public void setConfiguration(Properties props) {
		super.setConfiguration(props);

		log.error("Using Example SMS Plugin with hardcoded credentials - NOT FOR PRODUCTION");
	}
}

...