Use <cfhttp> to Find a Valid Redirect URL After Login

Tags | ColdFusion | User Defined Functions (UDF)

Posted on March 17, 2014 by Daria

One of the basic functionality of a login process is to redirect the user to the original page they requested before being caught up in the login process. But what if you can’t be assured that the page the user will be redirected to won’t error? What if the page the user is requesting is dependent on form variables being present that will be lost by the login process? My solution is to create a UDF to perform a check after login using the <cfhttp> tag to determine if it is a safe redirect url.

The first part of the process is to record the url of the original page the user requested. The following code would go in your Application.cfc file in the onSessionStart() method to set a session variable that includes the page as well as any url variables.

	session.referrer = cgi.SCRIPT_NAME & ( len(cgi.QUERY_STRING) ? "?" & cgi.QUERY_STRING : "" );

In your login processing functions, call the UDF to find the current referrer url.

	var userValid = true;// real user validation would happen here
	if ( local.userValid ) {
		var currReferrer = getLoginReferrer(
			errorString="Web Page Error Occurred",
		location (url=local.currReferrer, addtoken="false")

Finally, include the UDF in your login processing.

<cffunction name="getLoginReferrer" output="no" returntype="string"
	hint="I determine the redirect location to send a user after logging on.">
	<cfargument name="defaultLocation" required="yes" type="string" />
	<cfargument name="errorString" required="yes" type="string" />
	<cfargument name="excludePages" required="no" type="string" default="" />
	<cfargument name="excludeDelim" required="no" type="string" default="," />
	<cfargument name="referrerVar" required="no" type="string" default="referrer" />
	<cfargument name="sessionVars" required="no" type="struct" default="#session#" />

	<cfset var redirectLocation = arguments.defaultLocation />
	<cfset var currReferrer = "" />

	<cfif structKeyExists(arguments.sessionVars,arguments.referrerVar)
		and not listFind(arguments.excludePages,arguments.sessionVars[arguments.referrerVar])>

		<cfset currReferrer = arguments.sessionVars[arguments.referrerVar] />
		<cfset structDelete(arguments.sessionVars,arguments.referrerVar) />

			<cflock name="referrerCheck" timeout="30" throwontimeout="yes" type="exclusive">
				<cfhttp url="#currReferrer#" resolveurl="no" throwonerror="yes">
					<cfhttpparam type="cookie" name="CFID" value="#cookie.CFID#" />
					<cfhttpparam type="cookie" name="CFTOKEN" value="#cookie.CFTOKEN#" />
					<cfif structKeyExists(cookie,"JSESSIONID")>
						<cfhttpparam type="cookie" name="JSESSIONID" value="#cookie.JSESSIONID#" />

			<cfif findNoCase(arguments.errorString,cfhttp.FileContent)>
				<!--- if there was an error, but it was caught by a site-wide error handler, send to the default location --->
				<cfset redirectLocation = arguments.defaultLocation />
				<!--- if there was no error, send the user to the referrer location --->
				<cfset redirectLocation = currReferrer />

			<!--- if the cfhttp call to test the referrer page threw an error, just send the user to the default location instead --->
			<cfcatch type="any">
				<cfreturn arguments.defaultLocation />

	<cfreturn redirectLocation />