Skip to content

Instantly share code, notes, and snippets.

@smebberson
Created March 9, 2012 11:20
Show Gist options
  • Save smebberson/2006128 to your computer and use it in GitHub Desktop.
Save smebberson/2006128 to your computer and use it in GitHub Desktop.
Facebook oAuth and Graph API example
.DS_Store
WEB-INF

Facebook oAuth example

A simple example, using ColdFusion, demonstrating integration with Facebook oAuth.

In more detail

The code demonstrates using oAuth, to request various permissions for a Facebook application, with the aim to retrieve an authorisation code specific to the logged in Facebook user.

Next steps

You'll need the following to make use of the example:

  • create yourself a Facebook application (remember to enter an app domain that is accessible to Facebook and will resolve to your code; and use the same domain in the Website section)
  • update Application.cfc with your specific details including client id, app secret, redirect uri and the permissions you require
<cfcomponent displayname="facebookAuthExample" output="false" hint="Application">
<cfset this.name = 'facebookAuthExample' />
<cfset this.applicationTimeout = CreateTimeSpan(0, 1, 0, 0) />
<cfset this.sessionManagement = true />
<cffunction name="onApplicationStart" access="public" returntype="boolean" output="false" hint="Set out application variables">
<!--- setup facebook, so we have some application wide variables --->
<cfset defineFacebookVariables() />
<cfreturn true />
</cffunction>
<cffunction name="onRequestStart" access="public" returnType="boolean" output="false">
<!--- redefine the facebook variables, if required --->
<cfif isDefined('url.reinit') AND len(url.reinit)>
<cfset defineFacebookVariables() />
</cfif>
<cfreturn true />
</cffunction>
<!--- custom function --->
<cffunction name="defineFacebookVariables" access="private" returntype="struct" output="false" hint="Hint, setup the facebook variables">
<!--- customise this section, specific to your details --->
<cfset application.stFacebook = StructNew() />
<cfset application.stFacebook.client_id = '' />
<cfset application.stFacebook.app_secret = '' />
<cfset application.stFacebook.redirect_uri = '' />
<cfset application.stFacebook.permissions = '' />
<cfreturn application.stFacebook />
</cffunction>
</cfcomponent>
<cfcomponent output="false" displayname="Facebook Graph API Component" hint="Interact with the Facebook Graph API using ColdFusion">
<!--- use this to request an auth token --->
<cffunction name="getAuthToken" returnType="struct" access="public" output="false" displayname="Request an authorisation token">
<!--- arguments --->
<cfargument name="client_id" type="string" required="false" default="#application.stFacebook.client_id#" />
<cfargument name="app_secret" type="string" required="false" default="#application.stFacebook.app_secret#" />
<cfargument name="redirect_uri" type="string" required="false" default="#application.stFacebook.redirect_uri#" />
<cfargument name="code" type="string" required="true" />
<!--- local variables --->
<cfset var stGraph = StructNew() />
<cfset var stReturn = StructNew() />
<cftry>
<cfhttp url="https://graph.facebook.com/oauth/access_token" method="get" timeout="30" result="stGraph">
<cfhttpparam type="url" name="client_id" value="#arguments.client_id#" />
<cfhttpparam type="url" name="client_secret" value="#arguments.app_secret#" />
<cfhttpparam type="url" name="redirect_uri" value="#trim(arguments.redirect_uri)#" />
<cfhttpparam type="url" name="code" value="#trim(arguments.code)#" />
</cfhttp>
<cfcatch type="any">
<cfset stReturn = cfcatch />
</cfcatch>
</cftry>
<cfif structcount(stGraph)>
<cfset stReturn.access_token = rereplace(stGraph.filecontent, 'access_token=([a-zA-Z0-9]+).+', "\1") />
<cfset stReturn.token_expires = rereplace(stGraph.filecontent, '.+?expires=([0-9]+)', "\1") />
</cfif>
<cfreturn stReturn />
</cffunction>
<!--- Use this to get information about the current user --->
<cffunction name="getCurrentUser" returntype="struct" access="public" output="false" displayname="Get Current User" hint="Used in the authentication and app approval workflow, to get information about the user who just authorised an application">
<!--- arguments --->
<cfargument name="access_token" type="string" required="true" />
<!--- local variables --->
<cfset var stGraphRequest = StructNew() />
<cfset var stReturn = StructNew() />
<!--- attempt to post against the Graph API, catch coldfusion errors and return them if they occur --->
<cftry>
<cfhttp url="https://graph.facebook.com/me" method="get" timeout="30" result="stGraphRequest">
<cfhttpparam type="url" name="access_token" value="#arguments.access_token#" />
</cfhttp>
<cfcatch type="any">
<cfset stReturn.error = StructNew() />
<cfset stReturn.error.type = 'ColdFusion' />
<cfset stReturn.error.message = 'There was an error trying to retrieve the information from Facebook.' />
</cfcatch>
</cftry>
<!--- if we have some file content, let's deserialize the JSON and return it --->
<cfif structKeyExists(stGraphRequest, 'filecontent')>
<cfset stReturn = DeserializeJSON(stGraphRequest.filecontent) />
</cfif>
<cfreturn stReturn />
</cffunction>
<!--- Use this to post against the graph API --->
<cffunction name="graphCreate" returntype="struct" access="public" output="false" displayname="Create an entry in the Graph" hint="Use the following to create an entry in the Facebook graph">
<!--- arguments --->
<cfargument name="object" type="string" required="true" />
<cfargument name="graphId" type="string" required="true" />
<cfargument name="graphArguments" type="struct" required="false" default="#StructNew()#" />
<!--- local variables --->
<cfset var stReturn = StructNew() />
<!--- attempt to post against the Graph API, catch errors and return them if they occur --->
<cftry>
<cfhttp url="https://graph.facebook.com/#arguments.graphId#/#arguments.object#" method="post" timeout="30" result="stReturn">
<cfloop collection="#arguments.graphArguments#" item="item">
<cfhttpparam type="formField" name="#item#" value="#arguments.graphArguments[item]#">
</cfloop>
</cfhttp>
<cfcatch type="any">
<cfset stReturn = cfcatch />
</cfcatch>
</cftry>
<cfreturn stReturn />
</cffunction>
</cfcomponent>
<cfsetting enablecfoutputonly="true" />
<cfset oFacebook = CreateObject('component', 'facebook') />
<cfif isDefined('session.stFacebook') AND isDefined('session.stFacebook.access_token') AND len(session.stFacebook.access_token)>
<cfset stGraph = oFacebook.getCurrentUser(session.stFacebook.access_token) />
</cfif>
<cfoutput>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Facebook oAuth</title>
<style>
dl { overflow: hidden; }
dt { float: left; font-weight: bold; clear: left; margin: 0 5px 0 0; }
dt:after { content: ':'; }
dd { float: left; margin: 0 0 20px 0; }
</style>
</head>
<body>
<h1>Graph API results for me</h1>
</cfoutput>
<cfif isDefined('stGraph') AND NOT isDefined('stGraph.error')>
<cfoutput><dl></cfoutput>
<cfloop collection="#stGraph#" item="item">
<cfif NOT isStruct(stGraph[item])>
<cfoutput><dt>#item#</dt><dd>#stGraph[item]#</dd></cfoutput>
</cfif>
</cfloop>
<cfoutput></dl>
<h2>Next steps</h2>
<p>Generally the next step is store the following information, in a Facebook users table allowing the application to use the Graph API on behalf of the user, limited to the permissions granted by the user.</p>
<dl>
<dt>authorization code</dt>
<dd>#session.stFacebook.access_token#</dd>
<dt>user id</dt>
<dd>#stGraph['id']#</dd>
</dl>
</cfoutput>
<cfelse>
<cfoutput><p>Facebook returned an error.</p></cfoutput>
<cfdump var="#stGraph#" />
</cfif>
<cfoutput>
</body>
</html>
</cfoutput>
<cfsetting enablecfoutputonly="true" />
<cfset oFacebook = CreateObject('component', 'facebook') />
<cfparam name="oAuthState" default="0" />
<cfparam name="error" default="" />
<cfparam name="error_reason" default="" />
<cfparam name="error_description" default="" />
<cfparam name="code" default="" />
<!--- check for a redirected error by facebook --->
<cfif isDefined('url.error') AND len(url.error)>
<cfset oAuthState = -1 />
</cfif>
<!--- check for url.code, which means we've completed the first step --->
<cfif isDefined('url.code') AND len(url.code)>
<cfset oAuthState = 1 />
<cfset stAuthToken = oFacebook.getAuthToken(code=url.code) />
<cfset session.stFacebook = StructNew() />
<cfset session.stFacebook.access_token = stAuthToken.access_token />
<cfset session.stFacebook.token_expires = stAuthToken.token_expires />
</cfif>
<cfoutput>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Facebook oAuth</title>
</head>
<body>
</cfoutput>
<cfif oAuthState eq 0>
<cfoutput>
<p>This is an example of a basic Facebook oAuth integration, using ColdFusion.<br />
The example demonstrates authorising an application acquiring the authorisation code, and then grabbing the current Facebook users details.</p>
<p>Generally the next step would be to persist the authorisation code against the users id so that you can interact with the Graph API on behalf of a user at a later date.</p>
<a href="https://www.facebook.com/dialog/oauth?client_id=#application.stFacebook.client_id#&amp;redirect_uri=#application.stFacebook.redirect_uri#&amp;scope=#application.stFacebook.permissions#">Get started.</a>
</cfoutput>
<cfif NOT len(application.stFacebook.client_id) OR NOT len(application.stFacebook.redirect_uri) OR NOT len(application.stFacebook.permissions)>
<cfoutput><p><b>Please note:</b> this won't work until you update Application.cfc with the necessary variables.</p></cfoutput>
</cfif>
<cfelseif oAuthState eq -1>
<cfoutput>
<p>Whoops, looks like there has been an error! Details below.</p>
<dl>
<dt>error</dt>
<dd>#url.error#</dd>
<dt>error_reason</dt>
<dd>#url.error_reason#</dd>
<dt>error_description</dt>
<dd>#url.error_description#</dd>
</dl>
</cfoutput>
<cfelseif oAuthState eq 1>
<cfoutput>
<dl>
<dt>access_token</dt>
<dd>#session.stFacebook.access_token#<dd>
<dt>token_expires</dt>
<dd>#session.stFacebook.token_expires#</dd>
</dl>
<p><a href="/graph.cfm">Now query the graph for the users details.</a></p>
</cfoutput>
</cfif>
<cfoutput>
</body>
</html>
</cfoutput>
@cfcoderatcodefactory
Copy link

Hi - attempting to use your code, which looks great. Hope you can help.

I have entered the 'client_id' (called app id on the app config page), the app secret, a redirect uri (starting with http://localhost) and the requested permissions into the struct in Application.cfc.

When running index.cfm i get this error message:

Given URL is not allowed by the Application configuration.: One or more of the given URLs is not allowed by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains.

Why?

Can it be because I am using localhost in the site url and redirect url, or that I haven’t entered anything in the field for App domain on the app config. page?

@dawesi
Copy link

dawesi commented Nov 27, 2016

Just in case anyone else needs the answer to the above question:
https://www.facebook.com/help/community/question/542958419109491

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment