Articles in this section
Category / Section

Configure Email based OTP in Gluu Server with CASA in Gluu 4.3.1

Published:
33 mins read

This document explains how to use the Gluu Server’s included Email_2fa interception script to implement a two-step, two-factor authentication (2FA) process
with username/password as the first step, and an OTP received via email as the second step. We are going to use Janssen Casa to enable 2FA.

Prerequisite

  • Gluu Server
  • CASA
  • Email_2FA interception script
  • SMTP configuration

Core Gluu Server configuration

In this test setup, a Gluu 4.4.1 is installed with CASA.

SMTP Configuration

Configure the SMTP server by following the Gluu documentation.

Email_2FA interception script

  • Log in to Gluu Server oxTrust
  • Configuration > Person Authentication Script
  • Add a new script:
    • Name: Email2FA
    • Select SAML ACRs: Nothing required for this test setup.
    • Description: Email2FA
    • Programming Language: Jython
    • Level: according to your own need. 0 for now.
    • Custom property (key/value):
      • token_length: 5
      • token_lifetime: 2
    • Script:
        from org.gluu.oxauth.service import AuthenticationService
        from org.gluu.oxauth.service import UserService
        from org.gluu.oxauth.auth import Authenticator
        from org.gluu.oxauth.security import Identity
        from org.gluu.model.custom.script.type.auth import PersonAuthenticationType
        from org.gluu.model import SmtpConnectProtectionType
      
        from org.gluu.service.cdi.util import CdiUtil
        from org.gluu.service import CacheService
        from org.gluu.util import StringHelper
        from org.gluu.oxauth.util import ServerUtil
        from org.gluu.oxauth.service.common import ConfigurationService
        from org.gluu.oxauth.service.common import EncryptionService
        from org.gluu.jsf2.message import FacesMessages
        from org.gluu.model.casa import ApplicationConfiguration
        from org.gluu.persist.exception import AuthenticationException
        from org.gluu.persist import PersistenceEntryManager
        from org.gluu.util.security import SecurityProviderUtility
      
        from javax.faces.application import FacesMessage
        from datetime import datetime, timedelta
        from java.util import GregorianCalendar, TimeZone
        from java.io import File
        from java.io import FileInputStream
        from java.util import Enumeration, Properties
      
        from java.security import Security
        from java.security import KeyStore
      
        from javax.mail.internet import MimeMessage, InternetAddress
        from javax.mail import Session, Message, Transport
      
        from java.util import Arrays
      
        from org.gluu.service import MailService
      
        from javax.activation import CommandMap
      
        from org.bouncycastle.asn1 import ASN1EncodableVector
        from org.bouncycastle.asn1.cms import AttributeTable
        from org.bouncycastle.asn1.cms import IssuerAndSerialNumber
        from org.bouncycastle.asn1.smime import SMIMECapabilitiesAttribute
        from org.bouncycastle.asn1.smime import SMIMECapability
        from org.bouncycastle.asn1.smime import SMIMECapabilityVector
        from org.bouncycastle.asn1.smime import SMIMEEncryptionKeyPreferenceAttribute
        from org.bouncycastle.asn1.x500 import X500Name
        from org.bouncycastle.cert.jcajce import JcaCertStore
        from org.bouncycastle.cms import CMSAlgorithm
        from org.bouncycastle.cms.jcajce import JcaSimpleSignerInfoGeneratorBuilder
        from org.bouncycastle.cms.jcajce import JceCMSContentEncryptorBuilder
        from org.bouncycastle.cms.jcajce import JceKeyTransRecipientInfoGenerator
        from org.bouncycastle.mail.smime import SMIMEEnvelopedGenerator
        from org.bouncycastle.mail.smime import SMIMESignedGenerator
        from org.bouncycastle.mail.smime import SMIMEUtil
      
        import os.path
        import random
        import string
        import re
        import urllib
        import java
        try:
            import json
        except ImportError:
            import simplejson as json
      
        class EmailValidator():
            regex = '^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'
      
            def check(self, email):
      
                if(re.search(self.regex,email)):
                    print "EmailOTP.  - %s is a valid email format" % email
                    return True
                else:
                    print "EmailOTP.  - %s is an invalid email format" % email
                    return False
      
        class Token:
            #class that deals with string token
      
            def generateToken(self,lent):
                rand1="1234567890123456789123456789"
                rand2="9876543210123456789123456789"
                first = int(rand1[:int(lent)])
                first1 = int(rand2[:int(lent)])
                token = random.randint(first, first1)
                return token
      
        class PersonAuthentication(PersonAuthenticationType):
      
            def __init__(self, currentTimeMillis):
                self.currentTimeMillis = currentTimeMillis
                self.jks_keystore = None
                self.keystore_password = None
                self.alias = None
                self.sign_alg = None
      
            def init(self, customScript, configurationAttributes):
                print "EmailOTP.  - Initialization"
      
                #### Email Signing Code Begin ####
      
                jks_keystore_val = configurationAttributes.get("Signer_Cert_KeyStore")
                keystore_password_val = configurationAttributes.get("Signer_Cert_KeyStorePassword")
                alias_val = configurationAttributes.get("Signer_Cert_Alias")
                sign_alg_val = configurationAttributes.get("Signer_SignAlgorithm")
      
                if jks_keystore_val != None:
                    self.jks_keystore = jks_keystore_val.getValue2()
      
                if keystore_password_val != None:
                    self.keystore_password = keystore_password_val.getValue2()
      
                if alias_val != None:
                    self.alias = alias_val.getValue2()
      
                if sign_alg_val != None:
                    self.sign_alg = sign_alg_val.getValue2()
      
                print "EmailOTP.  - Initialization - Initialized successfully"
                return True
      
            def destroy(self, configurationAttributes):
                print "EmailOTP.  - Destroyed successfully"
                return True
      
            def getApiVersion(self):
                return 11
      
            def isValidAuthenticationMethod(self, usageType, configurationAttributes):
                return True
      
            def getAuthenticationMethodClaims(self, configurationAttributes):
                return None
      
            def getAlternativeAuthenticationMethod(self, usageType, configurationAttributes):
                return None
      
            def authenticate(self, configurationAttributes, requestParameters, step):
                print "EmailOTP. - Authenticate for step %s" % ( step )
                authenticationService = CdiUtil.bean(AuthenticationService)
                identity = CdiUtil.bean(Identity)
                credentials = identity.getCredentials()
      
                user_name = credentials.getUsername()
                user_password = credentials.getPassword()
      
                facesMessages = CdiUtil.bean(FacesMessages)
                facesMessages.setKeepMessages()
      
                subject = "Gluu Authentication Token"
      
                session_attributes = identity.getSessionId().getSessionAttributes()
      
                multipleEmails = session_attributes.get("emailIds")
      
                if step == 1:
                    try:
                         # Check if user authenticated already in another custom script
                        user2 = authenticationService.getAuthenticatedUser()
                        print "EmailOTP. - Authenticate: user2 = {}".format(user2)
      
                        if user2 == None:
                            credentials = identity.getCredentials()
                            user_name = credentials.getUsername()
                            user_password = credentials.getPassword()
      
                            user_name = credentials.getUsername()
                            print "Email 2FA - Authenticate: user_name = {}".format(user_name)
      
                            user_password = credentials.getPassword()
                            print "Email 2FA - Authenticate: user_password = {}".format(user_password)
      
                            logged_in = False
                            if (StringHelper.isNotEmptyString(user_name) and StringHelper.isNotEmptyString(user_password)):
                                userService = CdiUtil.bean(UserService)
                                logged_in = authenticationService.authenticate(user_name, user_password)
                                if logged_in is True:
                                    user2 = authenticationService.getAuthenticatedUser()
                                    emailIds = user2.getAttribute("oxEmailAlternate")
                                    if StringHelper.isEmptyString(emailIds):
                                        emailIds = '{ "email-ids":[{ "email":"%s","addedOn":0,"nickName":"%s" }]}' % ( user2.getAttribute("mail"), user2.getAttribute("mail") )
                                    data = json.loads(emailIds)
                                    if len(data['email-ids']) > 1:
                                        commaSeperatedEmailString = []
                                        for email in data['email-ids']:
                                            reciever_id = email['email']
                                            commaSeperatedEmailString.append(reciever_id)
                                        # setting this in session is used to determine if this is a 2 or 3 step flow
                                        identity.setWorkingParameter("emailIds", ",".join(commaSeperatedEmailString))
      
                            return logged_in
                    except AuthenticationException as err:
                        print err
                        return False
                else:
                    #Means the selection email page was used
                    user2 = authenticationService.getAuthenticatedUser()
      
                    multipleEmails = []
                    token = identity.getWorkingParameter("token")
      
                    emailIds = user2.getAttribute("oxEmailAlternate")
                    if StringHelper.isEmptyString(emailIds):
                        emailIds = '{ "email-ids":[{ "email":"%s","addedOn":0,"nickName":"%s" }]}' % ( user2.getAttribute("mail"), user2.getAttribute("mail") )
      
                    data = json.loads(emailIds)
      
                    # step2 and multiple email ids present, then user has been presented a choice of email which is fetched in OtpEmailLoginForm:indexOfEmail, send email
                    if step == 2 and len(data['email-ids']) > 1 :
      
                        for email in data['email-ids']:
                            reciever_id = email['email']
                            multipleEmails.append(reciever_id)
      
                        idx = ServerUtil.getFirstValue(requestParameters, "OtpEmailLoginForm:indexOfEmail")
                        if idx != None and token != None:
                            sendToEmail = multipleEmails[int(idx)]
                            print "EmailOtp. Sending email to : %s " % sendToEmail
                            email_validator = EmailValidator()
                            email_valid = email_validator.check(sendToEmail)
                            if email_valid == True:
                                body = "Here is your token: %s" % token
                                sender = EmailSender(self.jks_keystore, self.keystore_password, self.alias, self.sign_alg)
                                sender.sendEmail(sendToEmail, subject, body)
                                return True
                            else:
                                return False
                        else:
                            print "EmailOTP. Something wrong with index or token"
                            return False
                    # token verification - step 3 incase of email selection , else step 2
                    else:
                        input_token = ServerUtil.getFirstValue(requestParameters, "OtpEmailLoginForm:passcode").strip()
                        print "input token %s" % input_token
                        print "EmailOTP.  - Token input by user is %s" % input_token
      
                        token = str(identity.getWorkingParameter("token"))
                        min11 = int(identity.getWorkingParameter("sentmin"))
                        nww = datetime.now()
                        te = str(nww)
                        listew = te.split(':')
                        curtime = int(listew[1])
      
                        token_lifetime = int(configurationAttributes.get("token_lifetime").getValue2())
                        if ((min11<= 60) and (min11>= 50)):
                            if ((curtime>=50) and (curtime<=60)):
                                timediff1 =  curtime -  min11
                                if timediff1>token_lifetime:
                                    print "OTP Expired"
                                    facesMessages.add(FacesMessage.SEVERITY_ERROR, "OTP Expired")
                                    return False
                            elif ((curtime>=0) or (curtime<=10)):
                                timediff1 = 60 - min11
                                timediff1 =  timediff1 + curtime
                                if timediff1>token_lifetime:
                                    print "OTP Expired"
                                    facesMessages.add(FacesMessage.SEVERITY_ERROR, "OTP Expired")
                                    return False
      
                        if ((min11>=0) and (min11<=60) and (curtime>=0) and (curtime<=60)):
                            timediff2 = curtime - min11
                            if timediff2>token_lifetime:
                                print "OTP Expired"
                                facesMessages.add(FacesMessage.SEVERITY_ERROR, "OTP Expired")
                                return False
                        # compares token sent and token entered by user
                        print "Token from session: %s " % token
                        if input_token == token:
                            print "Email 2FA - token entered correctly"
                            identity.setWorkingParameter("token_valid", True)
      
                            return True
      
                        else:
                            facesMessages = CdiUtil.bean(FacesMessages)
                            facesMessages.setKeepMessages()
                            facesMessages.clear()
                            facesMessages.add(FacesMessage.SEVERITY_ERROR, "Wrong code entered")
                            print "EmailOTP. Wrong code entered"
                            return False
      
            def prepareForStep(self, configurationAttributes, requestParameters, step):
                print "EmailOTP.  - Preparing for step %s" % step
                authenticationService = CdiUtil.bean(AuthenticationService)
      
                user2 = authenticationService.getAuthenticatedUser()
      
                if user2 is None:
                    print "EmailOTP.  - Preparing for step %s - user2 is None" % step
      
                else:
                    print "EmailOTP.  - Preparing for step %s - user2 is not None" % step
      
                identity = CdiUtil.bean(Identity)
      
                if step == 1:
                    self.prepareUIParams(identity)
                    return True
      
                elif step == 2 and user2 is not None:
                    print "EmailOTP.  - Preparing for step %s - step == 2 and user2 is not None" % step        
      
                    uid = user2.getAttribute("uid")
                    identity = CdiUtil.bean(Identity)
                    self.prepareUIParams(identity)
      
                    lent = configurationAttributes.get("token_length").getValue2()
                    new_token = Token()
                    token = new_token.generateToken(lent)
      
                    subject = "Gluu Authentication Token"
                    body = "Here is your token: %s" % token
      
                    sender = EmailSender(self.jks_keystore, self.keystore_password, self.alias, self.sign_alg)
                    emailIds = user2.getAttribute("oxEmailAlternate")
      
                    if StringHelper.isEmptyString(emailIds):
                        emailIds = '{ "email-ids":[{ "email":"%s","addedOn":0,"nickName":"%s" }]}' % ( user2.getAttribute("mail"), user2.getAttribute("mail") )            
      
                    print "emailIds : %s" % emailIds
                    data = json.loads(emailIds)
      
                    #Attempt to send message now if user has only one email id
                    if len(data['email-ids']) == 1:
                        email = data['email-ids'][0]
                        print "EmailOTP.  email to - %s" % email['email']
                        sender.sendEmail( email['email'], subject, body)
      
                    else:
                        commaSeperatedEmailString = []
                        for email in data['email-ids']:
                            print "EmailOTP. Email to - %s" % email['email']
                            commaSeperatedEmailString.append(email['email'])
                        identity.setWorkingParameter("emailIds", ",".join(commaSeperatedEmailString))
      
                    otptime1 = datetime.now()
                    tess = str(otptime1)
                    listee = tess.split(':')
      
                    identity.setWorkingParameter("sentmin", listee[1])
                    identity.setWorkingParameter("token", token)
      
                    return True
      
                else:
                    self.prepareUIParams(identity)
                    return True
      
            def getExtraParametersForStep(self, configurationAttributes, step):
                return Arrays.asList("token","emailIds","token_valid","sentmin")
      
            def getCountAuthenticationSteps(self, configurationAttributes):
      
                print "EmailOTP. getCountAuthenticationSteps called"
      
                if CdiUtil.bean(Identity).getWorkingParameter("emailIds") == None:
                    print "EmailOTP. getCountAuthenticationSteps called - 2 steps"
                    return 2
                else:
                    print "EmailOTP. getCountAuthenticationSteps called - 3 steps"
                    return 3
      
            def getPageForStep(self, configurationAttributes, step):
                print "EmailOTP. getPageForStep called %s" % step
      
                defPage = "/casa/otp_email.xhtml"
                if step == 2:
                    if CdiUtil.bean(Identity).getWorkingParameter("emailIds") == None:
                        print "emailIds not set, returning otp_email page"
                        return defPage
                    else:
                        return "/casa/otp_email_prompt.xhtml"
                elif step == 3:
                    return defPage
                return ""
      
            def getNextStep(self, configurationAttributes, requestParameters, step):
                return -1
      
            def logout(self, configurationAttributes, requestParameters):
                return True
      
            def prepareUIParams(self, identity):
                print "EmailOTP. prepareUIParams. Reading UI branding params"
                cacheService = CdiUtil.bean(CacheService)
                email2FaAssets = cacheService.get("email_2fa_assets")
      
                if email2FaAssets == None:
                    #This may happen when cache type is IN_MEMORY, where actual cache is merely a local variable
                    #(a expiring map) living inside Casa webapp, not oxAuth webapp
      
                    sets = self.getSettings()
      
                    custPrefix = "/custom"
                    logoUrl = "/images/logo.png"
                    faviconUrl = "/images/favicon.ico"
                    if sets != None and (("extra_css" in sets and sets["extra_css"] != None) or sets["use_branding"]):
                        logoUrl = custPrefix + logoUrl
                        faviconUrl = custPrefix + faviconUrl
      
                    prefix = custPrefix if sets != None and sets["use_branding"] else ""
      
                    extra_css = None
                    if sets != None and "extra_css" in sets:
                        extra_css = sets["extra_css"]
      
                    email2FaAssets = {
                        "contextPath": "/casa",
                        "prefix" : prefix,
                        "faviconUrl" : faviconUrl,
                        "extraCss": extra_css,
                        "logoUrl": logoUrl
                    }
      
                #Setting a single variable with the whole map does not work...
                identity.setWorkingParameter("casa_contextPath", email2FaAssets['contextPath'])
                identity.setWorkingParameter("casa_prefix", email2FaAssets['prefix'])
                identity.setWorkingParameter("casa_faviconUrl", email2FaAssets['contextPath'] + email2FaAssets['faviconUrl'])
                identity.setWorkingParameter("casa_extraCss", email2FaAssets['extraCss'])
                identity.setWorkingParameter("casa_logoUrl", email2FaAssets['contextPath'] + email2FaAssets['logoUrl'])
      
            def getSettings(self):
                entryManager = CdiUtil.bean(PersistenceEntryManager)
                config = ApplicationConfiguration()
                try:
                    config = entryManager.find(config.getClass(), "ou=casa,ou=configuration,o=gluu")
                except:
                    print "getSettings. Error reading casa settings from DB"
                settings = None
                try:
                    settings = json.loads(config.getSettings())
                except:
                    print "getSettings. Error parsing casa settings from DB"
                return settings
      
            def hasEnrollments(self, configurationAttributes, user):
                values = user.getAttributeValues("oxEmailAlternate")
                if values != None:
                    return True
                else:
                    return False
      
        class EmailSender():
            #class that sends e-mail through smtp
      
            time_out = 5000
      
            def __init__(self, jks_keystore, keystore_password, alias, sign_alg):
                self.jks_keystore = jks_keystore
                self.keystore_password = keystore_password
                self.alias = alias
                self.sign_alg = sign_alg
      
                mc = CommandMap.getDefaultCommandMap()
      
                mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html")
                mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml")
                mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain")
                mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed")
                mc.addMailcap("message/rfc822;; x-java-content- handler=com.sun.mail.handlers.message_rfc822")        
      
            def getSmtpConfig(self):
                print "EmailSender.  - getSmtpConfig"
      
                smtp_config = None
                smtpconfig = CdiUtil.bean(ConfigurationService).getConfiguration().getSmtpConfiguration()
      
                if smtpconfig is None:
                    print "EmailSender.  - getSmtpConfig - SMTP CONFIG DOESN'T EXIST - Please configure"
      
                else:
                    encryption_service = CdiUtil.bean(EncryptionService)
                    smtp_config = {
                        'host' : smtpconfig.getHost(),
                        'port' : smtpconfig.getPort(),
                        'user' : smtpconfig.getUserName(),
                        'from' : smtpconfig.getFromEmailAddress(),
                        'from_name' : smtpconfig.getFromName(),
                        'pwd_decrypted' : encryption_service.decrypt(smtpconfig.getPassword()),
                        'connect_protection' : smtpconfig.getConnectProtection(),
                        'requires_authentication' : smtpconfig.isRequiresAuthentication(),
                        'server_trust' : smtpconfig.isServerTrust(),
      
                        'key_store' : smtpconfig.getKeyStore(),
                        'key_store_password' : smtpconfig.getKeyStorePassword(),
                        'key_store_alias' : smtpconfig.getKeyStoreAlias(),
                        'signing-algorithm' : smtpconfig.getSigningAlgorithm()
                    }
      
                print "EmailSender.  - getSmtpConfig - Successfully"
                return smtp_config
      
            def signMessage(self, jks_keystore, keystore_password, alias, signing_algorithm, message):
                print "EmailSender.  - signMessage"
      
                isAliasWithPrivateKey = False
      
                keystore_ext = self.getExtension(jks_keystore)
      
                print "EmailSender.  - signMessage - keystore_ext = %s" % keystore_ext
      
                if keystore_ext.lower() == ".jks":
                    keyStore = KeyStore.getInstance("JKS", SecurityProviderUtility.getBCProvider())
      
                elif keystore_ext.lower() == ".pkcs12":
                    keyStore = KeyStore.getInstance("PKCS12", SecurityProviderUtility.getBCProvider())
      
                elif keystore_ext.lower() == ".bcfks":
                    keyStore = KeyStore.getInstance("BCFKS", SecurityProviderUtility.getBCProvider())
      
                file = File(jks_keystore)
                keyStore.load(FileInputStream(file), list(keystore_password))
                es = keyStore.aliases()
      
                while (es.hasMoreElements()):
                    alias = es.nextElement()
                    if (keyStore.isKeyEntry(alias)):
                        isAliasWithPrivateKey = True
                        break
      
                if (isAliasWithPrivateKey):
                    pkEntry = keyStore.getEntry(alias,KeyStore.PasswordProtection(list(keystore_password)))
                    privateKey = pkEntry.getPrivateKey()
      
                chain = keyStore.getCertificateChain(alias)
      
                publicKey = chain[0]
      
                certificate = keyStore.getCertificate(alias)
      
                sign_algorithm = None
      
                if not signing_algorithm or not signing_algorithm.strip():
                    sign_algorithm = certificate.getSigAlgName()
                else:
                    sign_algorithm = signing_algorithm
      
                # Create the SMIMESignedGenerator
                capabilities = SMIMECapabilityVector()
                capabilities.addCapability(SMIMECapability.dES_EDE3_CBC)
                capabilities.addCapability(SMIMECapability.rC2_CBC, 128)
                capabilities.addCapability(SMIMECapability.dES_CBC)
                capabilities.addCapability(SMIMECapability.aES256_CBC)
      
                attributes = ASN1EncodableVector()
                attributes.add(SMIMECapabilitiesAttribute(capabilities))
      
                SMIMEUtil.createIssuerAndSerialNumberFor(certificate)
      
                issAndSer = IssuerAndSerialNumber(X500Name(publicKey.getIssuerDN().getName()),publicKey.getSerialNumber())        
      
                attributes.add(SMIMEEncryptionKeyPreferenceAttribute(issAndSer))
      
                signer = SMIMESignedGenerator()
      
                signer.addSignerInfoGenerator(JcaSimpleSignerInfoGeneratorBuilder().setProvider(SecurityProviderUtility.getBCProvider()).setSignedAttributeGenerator(AttributeTable(attributes)).build(sign_algorithm, privateKey, publicKey))
      
                # Add the list of certs to the generator
                certList = [publicKey]
      
                bcerts = JcaCertStore(certList)
                signer.addCertificates(bcerts)
      
                # Sign the message
                mm = signer.generate(message)
      
                # Set the content of the signed message
                message.setContent(mm, mm.getContentType())
                message.saveChanges()
      
                print "EmailSender.  - signMessage - Successfully"
                return message
      
            def sendEmail(self, user_email, message_subject, message_text):
                print "EmailSender.  - sendEmail"
      
                # server connection
                smtp_config = self.getSmtpConfig()
      
                properties = Properties()
      
                properties.put("mail.from", "Gluu Casa")
      
                smtp_connect_protect = smtp_config['connect_protection']
      
                if smtp_connect_protect == SmtpConnectProtectionType.StartTls:
      
                    properties.put("mail.transport.protocol", "smtp")
      
                    properties.put("mail.smtp.host", smtp_config['host'])
                    properties.put("mail.smtp.port", str(smtp_config['port']))
                    properties.put("mail.smtp.connectiontimeout", str(self.time_out))
                    properties.put("mail.smtp.timeout", str(self.time_out))
      
                    properties.put("mail.smtp.socketFactory.class", "com.sun.mail.util.MailSSLSocketFactory")
                    properties.put("mail.smtp.socketFactory.port", str(smtp_config['port']))
      
                    if smtp_config['server_trust'] == True:
                        properties.put("mail.smtp.ssl.trust", smtp_config['host'])
      
                    properties.put("mail.smtp.starttls.enable", "true")
                    properties.put("mail.smtp.starttls.required", "true")
      
                elif smtp_connect_protect == SmtpConnectProtectionType.SslTls:
      
                    properties.put("mail.transport.protocol.rfc822", "smtps")
      
                    properties.put("mail.smtp.host", smtp_config['host'])
                    properties.put("mail.smtp.port", str(smtp_config['port']))
                    properties.put("mail.smtp.connectiontimeout", str(self.time_out))
                    properties.put("mail.smtp.timeout", str(self.time_out))
      
                    properties.put("mail.smtp.socketFactory.class", "com.sun.mail.util.MailSSLSocketFactory")
                    properties.put("mail.smtp.socketFactory.port", str(smtp_config['port']))
      
                    if smtp_config['server_trust'] == True:
                        properties.put("mail.smtp.ssl.trust", smtp_config['host'])
      
                    properties.put("mail.smtp.ssl.enable", "true")
      
                session = Session.getDefaultInstance(properties)
      
                message = MimeMessage(session)
                message.setFrom(InternetAddress(smtp_config['from'], smtp_config['from_name']))
                message.addRecipient(Message.RecipientType.TO,InternetAddress(user_email))
                message.setSubject(message_subject)
                message.setContent(message_text, "text/html")
      
                if self.jks_keystore != None:
                    jks_keystore = self.jks_keystore
                else:
                    jks_keystore = smtp_config['key_store']
      
                if self.keystore_password != None:
                    keystore_password = self.keystore_password
                else:
                    keystore_password = smtp_config['key_store_password']
      
                if self.alias != None:
                    alias = self.alias
                else:
                    alias = smtp_config['key_store_alias']
      
                if self.sign_alg != None:
                    sign_alg = self.sign_alg
                else:
                    sign_alg = smtp_config['signing-algorithm']
      
                signed_message = self.signMessage(jks_keystore, keystore_password, alias, sign_alg, message)
      
                if smtp_connect_protect == SmtpConnectProtectionType.StartTls:
                    transport = session.getTransport("smtp")
      
                elif smtp_connect_protect == SmtpConnectProtectionType.SslTls:
                    transport = session.getTransport("smtps")
      
                transport.connect(properties.get("mail.smtp.host"),int(properties.get("mail.smtp.port")), smtp_config['user'], smtp_config['pwd_decrypted'])
                transport.sendMessage(signed_message, signed_message.getRecipients(Message.RecipientType.TO))
      
                transport.close()
      
                print "EmailSender.  - sendEmail - Successfully"
      
            def getExtension(self, file_path):
                file_name_with_ext = os.path.basename(file_path)
                file_name, ext = os.path.splitext(file_name_with_ext)
                return ext
      

CASA configuration

  • Log into CASA admin panel
  • Administrative console > Casa Plugins
  • Download email_2fa_core-4.4.1.Final-jar-with-dependencies.jar from https://maven.gluu.org/maven/org/gluu/casa/plugins/email_2fa_core/4.4.1.Final/
  • Upload this jar
  • After some time your plugin should be enabled. And you will see Email 2FA Core under 2FA credentials section
Was this article useful?
Like
Dislike
Help us improve this page
Please provide feedback or comments
Access denied
Access denied