Well, let me preface this by saying that the site I’m working on was not written by me. No excuse, but I’m doing my best to navigate my way around how CFM works. With that being said, I do have some familiarity on how SAML with Okta works. Our group has implemented SAML with Okta on several Apache Guacamole servers, 2 Gitlab servers, 3 Redmine servers, and 4 “in-house developed” PHP sites using OneLogin/PHP-SAML.
I configured the okta.json file using the application in my initial post. I copied it over to my application. So I have my app folder, then under that I have /config, /certs, /includes, and /saml. The Okta information was provided to me by our Okta team. I don’t have access to the settings. The /config/okta.json is similar to this:
{“companyName”:“redacted”,“consumeUrl”:https://mydomain.org/consume.cfm,“issuerUrl”:https://mydomain.org/saml,“issuerID”:http://www.okta.com/redacted/sso/saml,“certificate”:“-----BEGIN CERTIFICATE-----redacted-----END CERTIFICATE-----”,“createdOn”:“Wed, 26 Feb 2025 13:09:19 GMT”
}
Another user who was helping me sent me their code and I tried to implement some of it. They gave me an Application.cfc that I tried to adjust for my environment:
/**
*/
component{
this.name = “SATTS”;
this.sessionmanagement = true;
this.sessiontimeout = createTimeSpan(0,7,0,0);
this.triggerDataMember=true;
this.invokeImplicitAccessor=true;
// Mappings
this.mappings[‘/saml’] = getDirectoryFromPath(getCurrentTemplatePath()) & ‘/saml’
// java settings
this.javaSettings = {
LoadPaths : [“/saml/jars”],
reloadOnChange : true,
watchInterval : 60
};
public boolean function onApplicationStart() {
application.datasource=“FAA Okta”;
return true;
}
public boolean function onRequestStart(){
request.identityProvider = “okta”;
request.rootDir = “SATTS”
request.siteURL = “http” & (cgi.server_port_secure ? “s” : “”) & “:” & “//” & cgi.server_name & “:” & cgi.server_port & “/” & request.rootDir;
if (structKeyExists(url,“reload”)){
location(“./”,false);
}
// check if identityProvider is setup and configured
if (!isNull(request.identityProvider)){
try{
data = deserializeJson(fileRead(‘config/#request.identityProvider#.json’));
request.identityProviderModel = createObject(‘component’, ‘saml.providers.’ & request.identityProvider).init(argumentCollection = data)
}catch (any e){
request.identityProviderModel = createObject(‘component’, ‘saml.providers.’ & request.identityProvider).init()
}
if (isNull(request.identityProviderModel)){
request.identityProviderModel = createObject(‘component’, ‘saml.providers.’ & request.identityProvider).init()
}
// relocate to admin if not completely setup
if (!findNoCase(“admin”,cgi.script_name) && !request.identityProviderModel.isReady())
location(“/#request.rootDir#/admin.cfm”,false);
}
return true;
}
}
There’s also a post.cfm:
try{
isssuerFinalUrl = request.identityProviderModel.getRedirectToIdentityProviderUrl()
// now send to identity provider
location ( isssuerFinalUrl, false);
}
catch(Any e){
writeDump(e);
}
And a consumer.cfm but it’s really geared towards their environment.
So in the spirit of “starting from scratch”, should the flow be something like this? And the first basic question on this is what’s the default entry point)?:
→ /post.cfm → Okta → consume.cfm → index.cfm?
Thanks!
Harry