Pete Freitag Pete Freitag

Adding Two Factor Authentication to ColdFusion Administrator

Updated on November 20, 2023
By Pete Freitag
coldfusion

A few months back I was researching two/multi factor authentication solutions to employ to meet PCI compliance, I came across a somewhat new company called DuoSecurity.

If your not familiar with two factor authentication the basic premis is that in order to authenticate you must provide more than one type of authentication, for example Something you know (a password), and Something you have (a hardware token device, a smart card, or a smartphone).

DuoSecurity's solution to this problem was compelling because they allow you to use a smartphone for your second factor by sending a push notification, you simply tap approve, and you're in. This is much easier they keying in a code for the end user (though they also support that via text message, or landline phone call) .

After I had integrated this solution into a SSH server for authentication, the folks at Duo asked if I would be interested in writing a ColdFusion port of their DuoWeb API (which allows you to use their technology to authenticate into Web Applications). I ofcourse said yes, and you can download duo_web for ColdFusion on github.

Here's a video showing how the push technology works:

Next I thought hey it would be great if you could add Two Factor Authentication to ColdFusion Administrator, and it turns out you can:

Setup Duo Security

  1. Sign up for an account at DuoSecurity you can create an account for up to 10 users for free.
  2. Next create a new integration in your account, for integration type select "Web SDK"
  3. An integration key, a secret key, and an API hostname will be generated for you to use below.

Now Download duo_coldfusion and place it in the web root of the site used to login to ColdFusion administrator.

Next create an Application.cfc file in the /CFIDE/administrator directory with the following code:

<cfcomponent>
	<cfset this.name = "cfadmin">
	<cfset this.sessionmanagement = true>
	
	<cfset variables.appKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
	<cfset variables.iKey = "XXXXXXXXX">
	<cfset variables.sKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
	<cfset variables.duoHost = "api-XXXXXXXX.duosecurity.com">
	
	
	<cffunction name="OnRequest">
		<cfargument name="template">
		<cfinclude template="Application.cfm">
		<cfset var local = StructNew()>
		<cfif arguments.template contains "logout.cfm" AND isAuthenticatedTwoFactor()>
			<cfset StructDelete(session, "duoAuthenticated")>
			<cfinclude template="#arguments.template#">
			<cfreturn>
		</cfif>
		<cfif StructKeyExists(form, "sig_response")>
			<cfset local.duo_user = CreateObject("component", "duo_coldfusion.DuoWeb").verifyResponse(iKey=variables.iKey, aKey = variables.appKey, sKey=variables.sKey, sig_response=form.sig_response)>
			<cfif local.duo_user IS "pete">
				<cfset session.duoAuthenticated = true>
			</cfif>
		</cfif>
		<cfif IsUserLoggedIn() AND NOT isAuthenticatedTwoFactor()>
			<cfset local.post_action = "/CFIDE/administrator/index.cfm">
			<cfset session.duo_sig_request = CreateObject("component", "duo_coldfusion.DuoWeb").signRequest(iKey=variables.iKey, aKey = variables.appKey, sKey=variables.sKey, username=GetAuthUser())>
			<!--- show second factor authenication page --->
			<!doctype html>
			<html>
				<head>
					<title>Please Authenticate</title>
					<script src="/duo_coldfusion/js/Duo-Web-v1.bundled.min.js"></script>
					<cfoutput>
					<script>
					  Duo.init({
					    'host': '#JSStringFormat(variables.duoHost)#',
					    'sig_request': '#JSStringFormat(session.duo_sig_request)#',
					    'post_action': ''
					  });
					</script>
					</cfoutput>
				</head>
				<body>
					<h2>Authenticate</h2>
					<iframe id="duo_iframe" width="100%" height="500" frameborder="0"></iframe>
				</body>
			</html>
		<cfelse>
			<!--- two factor authentication --->
			<cfinclude template="#arguments.template#">	
		</cfif>
		
	</cffunction>
	
	<cffunction name="isAuthenticatedTwoFactor" returntype="boolean">
		<cfreturn StructKeyExists(session, "duoAuthenticated") AND session.duoAuthenticated>
	</cffunction>

</cfcomponent>

Next you need to generate a unique value for variables.appKey it MUST be 40 chars long. Plug in the values you got on the duo web site when you created your integration for the variables.iKey (integration key), variables.sKey (secret key), and the variables.duoHost.

<cfset variables.appKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
<cfset variables.iKey = "XXXXXXXXX">
<cfset variables.sKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX">
<cfset variables.duoHost = "api-XXXXXXXX.duosecurity.com">

Finally go and log into the ColdFusion administrator, after you enter your password you will be given a prompt which will let you pick your second factor method. If it authenticates you will be logged in and send to the CF Administrator.

It will look something like this when you are up and running:



coldfusion security authentication two factor duosecurity

Adding Two Factor Authentication to ColdFusion Administrator was first published on September 19, 2011.

If you like reading about coldfusion, security, authentication, two factor, or duosecurity then you might also like:

Fixinator

The Fixinator Code Security Scanner for ColdFusion & CFML is an easy to use security tool that every CF developer can use. It can also easily integrate into CI for automatic scanning on every commit.


Try Fixinator

CFBreak
The weekly newsletter for the CFML Community


Comments

Hey Pete,

After I approve the login, the authenticate page just reloads. Can't get past it no matter which method I choose.
by Derek on 12/24/2011 at 1:07:17 AM UTC
@Derek - Try adding a <cfdump var="#session#"> and <cfoutput> IsUserLoggedIn(): #IsUserLoggedIn()#</cfoutput> under the iframe tag and see what shows up.
by Pete Freitag on 01/27/2012 at 4:02:02 PM UTC
ok, i am revisiting this. still having the issue and isloggedin says YES and I have a duo_sig_request
by Derek on 10/21/2012 at 8:27:35 PM UTC
finally figured it out

<cfif local.duo_user IS "pete">
<cfset session.duoAuthenticated = true>
</cfif>

Whomever else reads this, change this to the username in your DUO users admin area.
by Derek on 10/21/2012 at 8:47:06 PM UTC