CF2025 Update 8: Native Passkey Support Comes to ColdFusion

Adobe ColdFusion 2025 Update 8 introduced several important platform improvements, but one of the most practical security additions is native passkey support.

Passkeys allow ColdFusion applications to support passwordless authentication using WebAuthn and FIDO2. In practical terms, this means users can sign in with options like Touch ID, Face ID, Windows Hello, a device PIN, or a hardware security key instead of typing a password.

Why Passkeys Matter

Passwords have always been one of the weakest parts of web application security. Users reuse them, forget them, choose weak ones, and can be tricked into entering them on fake websites.

Passkeys help solve many of these problems by replacing passwords with public/private key authentication. When a user registers a passkey, the private key stays on the user’s device. ColdFusion stores the public key. During login, ColdFusion sends a challenge, the user’s device signs that challenge, and ColdFusion verifies the result.

The important part is that the user never sends a password to the server. That means there is no password for an attacker to steal, reuse, or trick the user into typing somewhere else.

What ColdFusion 2025 Update 8 Adds

ColdFusion 2025 Update 8 adds native passkey functions that allow developers to register and authenticate users with passkeys directly from CFML.

The main passkey functions are:

  • PasskeyRegister(userStruct, configStruct)
  • PasskeyAuthenticate(userStruct, configStruct)
  • PasskeyGetResult(token)

The basic flow is simple:

  • A user registers a passkey.
  • ColdFusion stores the credential information.
  • The user later signs in with that passkey.
  • ColdFusion verifies the result and logs the user in.

Requirements

Before adding passkeys to a ColdFusion application, you need:

  • Adobe ColdFusion 2025 Update 8 or later
  • A browser that supports WebAuthn
  • HTTPS in production
  • A device that supports biometric authentication, PIN authentication, or a hardware security key

For local development, WebAuthn browser support usually works on localhost. For production, passkeys should be used over HTTPS.

Passkey Registration Flow

Passkey registration is the process of creating a passkey and connecting it to a user account.

A common registration flow looks like this:

  • The user signs in with their existing account.
  • The application shows a “Create a passkey” button.
  • ColdFusion calls PasskeyRegister().
  • The browser prompts the user to create a passkey.
  • The user confirms with their device.
  • ColdFusion stores the public key.

Here is a simplified registration example:

<cfscript>
userStruct = {
    name: "[email protected]",
    displayName: "User Example",
    rpName: "My ColdFusion App",
    rpId: cgi.server_name,
    userVerification: "preferred"
};

configStruct = {
    successHandler: "onRegisterSuccess",
    errorHandler: "onRegisterError",
    redirectUrl: "/passkey-callback.cfm",
    service: "/CFIDE/passkey/DatabasePasskey.cfc"
};

PasskeyRegister(userStruct, configStruct);
</cfscript>

In this example, PasskeyRegister() prepares the registration process on the ColdFusion side.

Passkey Authentication Flow

Authentication is the sign-in step. Once a user has registered a passkey, they can use it to log in without typing a password.

A common authentication flow looks like this:

  • The user visits the login page.
  • The application shows a “Sign in with passkey” button.
  • ColdFusion calls PasskeyAuthenticate().
  • The browser prompts the user to use their passkey.
  • ColdFusion verifies the result.
  • The application creates the user session.

Here is a simplified authentication example:

<cfscript>
userStruct = {
    rpId: cgi.server_name,
    userVerification: "preferred"
};

configStruct = {
    successHandler: "onAuthSuccess",
    errorHandler: "onAuthError",
    redirectUrl: "/passkey-callback.cfm",
    service: "/CFIDE/passkey/DatabasePasskey.cfc"
};

PasskeyAuthenticate(userStruct, configStruct);
</cfscript>

This allows the browser to present available passkeys for the current site. That creates a clean “Sign in with passkey” experience where the user does not have to type their email address first.

Handling the Callback

After registration or authentication, ColdFusion redirects to the callback URL with a passkey token. The callback page should call PasskeyGetResult() to retrieve the result.

It is important to check the action type before logging the user in. A registration result should not automatically be treated as a successful login.

<cfparam name="url.passkey_token" default="">

<cfif structKeyExists(url, "passkey_token") AND len(trim(url.passkey_token))>

    <cfset result = PasskeyGetResult(url.passkey_token)>

    <cfif result.success>

        <cfif result.action EQ "authentication">

            <cfset userRoles = getUserRoles(result.username)>

            <cfset sessionRotate()>

            <cflogin>
                <cfloginuser
                    name="#result.username#"
                    password=""
                    roles="#userRoles#">
            </cflogin>

            <cflocation url="/dashboard.cfm" addtoken="false">

        <cfelseif result.action EQ "registration">

            <cfset session.passkeyRegistered = true>
            <cflocation url="/passkey-authenticate.cfm" addtoken="false">

        </cfif>

    <cfelse>

        <cfset session.passkeyError = result.message>
        <cflocation url="/login.cfm" addtoken="false">

    </cfif>

<cfelse>

    <cflocation url="/login.cfm" addtoken="false">

</cfif>

Storage Options

ColdFusion provides built-in passkey storage options.

For development or simple single-server testing, Adobe provides:

/CFIDE/passkey/DefaultPasskey.cfc

That option stores passkey data in JSON files on the local server.

For production, use:

/CFIDE/passkey/DatabasePasskey.cfc

The database-backed option is the better choice for real applications, especially if the application runs on more than one server or may eventually be moved into a clustered environment.

Security Recommendations

Passkeys are much stronger than passwords, but the surrounding application still needs to be designed carefully.

  • Use HTTPS in production.
  • Set rpId explicitly and make sure it matches your domain.
  • Do not build rpId from user input.
  • Use fixed or allowlisted redirect URLs.
  • Do not pass user-supplied URLs directly into redirectUrl.
  • Use DatabasePasskey.cfc in production.
  • Keep password login available during migration.
  • Handle browser and device errors gracefully.
  • Check result.action before creating a login session.
  • Rotate the session after successful authentication.

A Practical Migration Strategy

For existing ColdFusion applications, I would not remove password authentication immediately. A safer rollout is to introduce passkeys gradually.

  • Keep the current username and password login.
  • After a successful login, invite the user to create a passkey.
  • Allow the user to skip passkey setup at first.
  • After registration, show “Sign in with passkey” on the login page.
  • Keep password login available as a fallback.
  • Add account recovery rules before making passkeys mandatory.

Final Thoughts

ColdFusion 2025 Update 8 is a significant update, and native passkey support is one of the most useful security additions.

For new applications, passkeys are worth considering from the start. For existing applications, they are a strong candidate for an optional “better login” path that can be introduced gradually.

The main thing is to treat passkeys as part of the overall authentication design, not just a drop-in button. You still need good session handling, clear recovery flows, safe redirects, proper role lookup, and production-ready credential storage.

With ColdFusion 2025 Update 8, Adobe has given ColdFusion developers native tools to build modern passwordless authentication directly into their applications.

Adobe ColdFusion 2025 Update 8 introduced several important platform improvements, but one of the most practical security additions is native passkey support.

Passkeys allow ColdFusion applications to support passwordless authentication using WebAuthn and FIDO2. In practical terms, this means users can sign in with options like Touch ID, Face ID, Windows Hello, a device PIN, or a hardware security key instead of typing a password.

Why Passkeys Matter

Passwords have always been one of the weakest parts of web application security. Users reuse them, forget them, choose weak ones, and can be tricked into entering them on fake websites.

Passkeys help solve many of these problems by replacing passwords with public/private key authentication. When a user registers a passkey, the private key stays on the user’s device. ColdFusion stores the public key. During login, ColdFusion sends a challenge, the user’s device signs that challenge, and ColdFusion verifies the result.

The important part is that the user never sends a password to the server. That means there is no password for an attacker to steal, reuse, or trick the user into typing somewhere else.

What ColdFusion 2025 Update 8 Adds

ColdFusion 2025 Update 8 adds native passkey functions that allow developers to register and authenticate users with passkeys directly from CFML.

The main passkey functions are:

  • PasskeyRegister(userStruct, configStruct)
  • PasskeyAuthenticate(userStruct, configStruct)
  • PasskeyGetResult(token)

The basic flow is simple:

  • A user registers a passkey.
  • ColdFusion stores the credential information.
  • The user later signs in with that passkey.
  • ColdFusion verifies the result and logs the user in.

Requirements

Before adding passkeys to a ColdFusion application, you need:

  • Adobe ColdFusion 2025 Update 8 or later
  • A browser that supports WebAuthn
  • HTTPS in production
  • A device that supports biometric authentication, PIN authentication, or a hardware security key

For local development, WebAuthn browser support usually works on localhost. For production, passkeys should be used over HTTPS.

Passkey Registration Flow

Passkey registration is the process of creating a passkey and connecting it to a user account.

A common registration flow looks like this:

  • The user signs in with their existing account.
  • The application shows a “Create a passkey” button.
  • ColdFusion calls PasskeyRegister().
  • The browser prompts the user to create a passkey.
  • The user confirms with their device.
  • ColdFusion stores the public key.

Here is a simplified registration example:

<cfscript>
userStruct = {
    name: "[email protected]",
    displayName: "User Example",
    rpName: "My ColdFusion App",
    rpId: cgi.server_name,
    userVerification: "preferred"
};

configStruct = {
    successHandler: "onRegisterSuccess",
    errorHandler: "onRegisterError",
    redirectUrl: "/passkey-callback.cfm",
    service: "/CFIDE/passkey/DatabasePasskey.cfc"
};

PasskeyRegister(userStruct, configStruct);
</cfscript>

In this example, PasskeyRegister() prepares the registration process on the ColdFusion side.

Passkey Authentication Flow

Authentication is the sign-in step. Once a user has registered a passkey, they can use it to log in without typing a password.

A common authentication flow looks like this:

  • The user visits the login page.
  • The application shows a “Sign in with passkey” button.
  • ColdFusion calls PasskeyAuthenticate().
  • The browser prompts the user to use their passkey.
  • ColdFusion verifies the result.
  • The application creates the user session.

Here is a simplified authentication example:

<cfscript>
userStruct = {
    rpId: cgi.server_name,
    userVerification: "preferred"
};

configStruct = {
    successHandler: "onAuthSuccess",
    errorHandler: "onAuthError",
    redirectUrl: "/passkey-callback.cfm",
    service: "/CFIDE/passkey/DatabasePasskey.cfc"
};

PasskeyAuthenticate(userStruct, configStruct);
</cfscript>

This allows the browser to present available passkeys for the current site. That creates a clean “Sign in with passkey” experience where the user does not have to type their email address first.

Handling the Callback

After registration or authentication, ColdFusion redirects to the callback URL with a passkey token. The callback page should call PasskeyGetResult() to retrieve the result.

It is important to check the action type before logging the user in. A registration result should not automatically be treated as a successful login.

<cfparam name="url.passkey_token" default="">

<cfif structKeyExists(url, "passkey_token") AND len(trim(url.passkey_token))>

    <cfset result = PasskeyGetResult(url.passkey_token)>

    <cfif result.success>

        <cfif result.action EQ "authentication">

            <cfset userRoles = getUserRoles(result.username)>

            <cfset sessionRotate()>

            <cflogin>
                <cfloginuser
                    name="#result.username#"
                    password=""
                    roles="#userRoles#">
            </cflogin>

            <cflocation url="/dashboard.cfm" addtoken="false">

        <cfelseif result.action EQ "registration">

            <cfset session.passkeyRegistered = true>
            <cflocation url="/passkey-authenticate.cfm" addtoken="false">

        </cfif>

    <cfelse>

        <cfset session.passkeyError = result.message>
        <cflocation url="/login.cfm" addtoken="false">

    </cfif>

<cfelse>

    <cflocation url="/login.cfm" addtoken="false">

</cfif>

Storage Options

ColdFusion provides built-in passkey storage options.

For development or simple single-server testing, Adobe provides:

/CFIDE/passkey/DefaultPasskey.cfc

That option stores passkey data in JSON files on the local server.

For production, use:

/CFIDE/passkey/DatabasePasskey.cfc

The database-backed option is the better choice for real applications, especially if the application runs on more than one server or may eventually be moved into a clustered environment.

Security Recommendations

Passkeys are much stronger than passwords, but the surrounding application still needs to be designed carefully.

  • Use HTTPS in production.
  • Set rpId explicitly and make sure it matches your domain.
  • Do not build rpId from user input.
  • Use fixed or allowlisted redirect URLs.
  • Do not pass user-supplied URLs directly into redirectUrl.
  • Use DatabasePasskey.cfc in production.
  • Keep password login available during migration.
  • Handle browser and device errors gracefully.
  • Check result.action before creating a login session.
  • Rotate the session after successful authentication.

A Practical Migration Strategy

For existing ColdFusion applications, I would not remove password authentication immediately. A safer rollout is to introduce passkeys gradually.

  • Keep the current username and password login.
  • After a successful login, invite the user to create a passkey.
  • Allow the user to skip passkey setup at first.
  • After registration, show “Sign in with passkey” on the login page.
  • Keep password login available as a fallback.
  • Add account recovery rules before making passkeys mandatory.

Final Thoughts

ColdFusion 2025 Update 8 is a significant update, and native passkey support is one of the most useful security additions.

For new applications, passkeys are worth considering from the start. For existing applications, they are a strong candidate for an optional “better login” path that can be introduced gradually.

The main thing is to treat passkeys as part of the overall authentication design, not just a drop-in button. You still need good session handling, clear recovery flows, safe redirects, proper role lookup, and production-ready credential storage.

With ColdFusion 2025 Update 8, Adobe has given ColdFusion developers native tools to build modern passwordless authentication directly into their applications.

Cool Stuff

Testing Pantheon Autopilot: A Safer Path to Automated WordPress Updates

Automating WordPress Core and plugin updates has long been one of those ideas that sounds great in theory—but makes seasoned WordPress developers nervous in practice.

read more

How Docker Streamlines Our CF Development

We adopted Docker to make local environments consistent, fast to spin up, and easy to share across the team without manual setup drift or “works on my machine” surprises across our stack.

read more

Perfectly Balanced Text: How to Use text-wrap: balance; in CSS

In modern UX design, it's often the little details that make a website feel polished and professional. One of those details? Perfectly balanced text in headings and paragraphs.

read more