FusionAuth developer image
FusionAuth developer logo
  • Back to site
  • Expert Advice
  • Blog
  • Developers
  • Downloads
  • Account
  • Contact sales
Navigate to...
  • Welcome
  • Getting Started
  • 5-Minute Setup Guide
  • Release Notes
  • Core Concepts
    • Overview
    • Users
    • Roles
    • Groups
    • Entity Management
    • Registrations
    • Applications
    • Tenants
    • Identity Providers
    • Key Master
    • SCIM
    • Search
    • Authentication and Authorization
    • Integration Points
    • Localization and Internationalization
    • Editions and Features
    • Roadmap
  • Installation Guide
    • Overview
    • System Requirements
    • Server Layout
    • Cloud
    • Cluster
    • Docker
    • Fast Path
    • Kubernetes
      • Overview
      • Deployment Guide
      • Minikube Setup
      • Amazon EKS Setup
      • Google GKE Setup
      • Microsoft AKS Setup
    • Kickstart™
    • Homebrew
    • Packages
    • Database
    • FusionAuth App
    • FusionAuth Search
    • Common Configuration
  • Admin Guide
    • Overview
    • Config Management
    • Licensing
    • Monitoring
    • Proxy Setup
    • Securing
    • Technical Support
    • Troubleshooting
    • Upgrading
  • Migration Guide
    • Overview
    • General
    • Auth0
    • Keycloak
    • Amazon Cognito
    • Tutorial
  • APIs
    • Overview
    • Authentication
    • Errors
    • Actioning Users
    • API Keys
    • Applications
    • Audit Logs
    • Connectors
      • Overview
      • Generic
      • LDAP
    • Consents
    • Emails
    • Entity Management
      • Overview
      • Entities
      • Entity Types
      • Grants
    • Event Logs
    • Families
    • Forms
    • Form Fields
    • Groups
    • Identity Providers
      • Overview
      • Links
      • Apple
      • External JWT
      • Epic Games
      • Facebook
      • Google
      • HYPR
      • LinkedIn
      • Nintendo
      • OpenID Connect
      • SAML v2
      • SAML v2 IdP Initiated
      • Sony PlayStation Network
      • Steam
      • Twitch
      • Twitter
      • Xbox
    • Integrations
    • IP Access Control Lists
    • JWT
    • Keys
    • Lambdas
    • Login
    • Message Templates
    • Messengers
      • Overview
      • Generic
      • Kafka
      • Twilio
    • Multi-Factor/Two Factor
    • Passwordless
    • Reactor
    • Registrations
    • Reports
    • SCIM
      • Overview
      • SCIM EnterpriseUser
      • SCIM Group
      • SCIM Service Provider Config.
      • SCIM User
    • System
    • Tenants
    • Themes
    • Users
    • User Actions
    • User Action Reasons
    • User Comments
    • Webhooks
  • Client Libraries
    • Overview
    • Dart
    • Go
    • Java
    • JavaScript
    • .NET Core
    • Node
    • OpenAPI
    • PHP
    • Python
    • Ruby
    • Typescript
  • Themes
    • Overview
    • Examples
    • Helpers
    • Localization
    • Template Variables
  • Email & Templates
    • Overview
    • Configure Email
    • Email Templates
    • Email Variables
    • Message Templates
  • Events & Webhooks
    • Overview
    • Writing a Webhook
    • Securing Webhooks
    • Events
      • Overview
      • Audit Log Create
      • Event Log Create
      • JWT Public Key Update
      • JWT Refresh
      • JWT Refresh Token Revoke
      • Kickstart Success
      • User Action
      • User Bulk Create
      • User Create
      • User Create Complete
      • User Deactivate
      • User Delete
      • User Delete Complete
      • User Email Update
      • User Email Verified
      • User IdP Link
      • User IdP Unlink
      • User Login Failed
      • User Login Id Duplicate Create
      • User Login Id Duplicate Update
      • User Login New Device
      • User Login Success
      • User Login Suspicious
      • User Password Breach
      • User Password Reset Send
      • User Password Reset Start
      • User Password Reset Success
      • User Password Update
      • User Reactivate
      • User Registration Create
      • User Registration Create Complete
      • User Registration Delete
      • User Registration Delete Complete
      • User Registration Update
      • User Registration Update Complete
      • User Registration Verified
      • User Two Factor Method Add
      • User Two Factor Method Remove
      • User Update
      • User Update Complete
  • Example Apps
    • Overview
    • Dart
    • Go
    • Java
    • JavaScript
    • .NET Core
    • PHP
    • Python
    • Ruby
  • Lambdas
    • Overview
    • Apple Reconcile
    • Client Cred. JWT Populate
    • Epic Games Reconcile
    • External JWT Reconcile
    • Facebook Reconcile
    • Google Reconcile
    • HYPR Reconcile
    • JWT Populate
    • LDAP Connector Reconcile
    • LinkedIn Reconcile
    • Nintendo Reconcile
    • OpenID Connect Reconcile
    • SAML v2 Populate
    • SAML v2 Reconcile
    • SCIM Group Req. Converter
    • SCIM Group Resp. Converter
    • SCIM User Req. Converter
    • SCIM User Resp. Converter
    • Sony PSN Reconcile
    • Steam Reconcile
    • Twitch Reconcile
    • Twitter Reconcile
    • Xbox Reconcile
  • Identity Providers
    • Overview
    • Apple
    • Epic Games
    • External JWT
      • Overview
      • Example
    • Facebook
    • Google
    • HYPR
    • LinkedIn
    • Nintendo
    • OpenID Connect
      • Overview
      • Azure AD
      • Discord
      • Github
    • Sony PlayStation Network
    • Steam
    • Twitch
    • Twitter
    • SAML v2
      • Overview
      • ADFS
    • SAML v2 IdP Initiated
      • Overview
      • Okta
    • Xbox
  • Messengers
    • Overview
    • Generic Messenger
    • Kafka Messenger
    • Twilio Messenger
  • Connectors
    • Overview
    • Generic Connector
    • LDAP Connector
    • FusionAuth Connector
  • Self Service Account Mgmt
    • Overview
    • Updating User Data & Password
    • Add Two-Factor Authenticator
    • Add Two-Factor Email
    • Add Two-Factor SMS
    • Customizing
    • Troubleshooting
  • Advanced Threat Detection
    • Overview
  • Integrations
    • Overview
    • CleanSpeak
    • Kafka
    • Twilio
  • OpenID Connect & OAuth 2.0
    • Overview
    • Endpoints
    • Tokens
  • SAML v2 IdP
    • Overview
    • Google
    • Zendesk
  • Plugins
    • Plugins
    • Writing a Plugin
    • Custom Password Hashing
  • Guides
    • Overview
    • Advanced Registration Forms
    • Breached Password Detection
    • Multi-Factor Authentication
    • Multi-Tenant
    • Passwordless
    • Securing Your APIs
    • Silent Mode
    • Single Sign-on
  • Tutorials
    • Overview
    • User Control & Gating
      • Gate Unverified Users
      • Gate Unverified Registrations
      • User Account Lockout
    • Setup Wizard & First Login
    • Register/Login a User
    • Start and Stop FusionAuth
    • Authentication Tokens
    • Key Rotation
    • JSON Web Tokens
    • Prometheus Setup
    • Switch Search Engines
    • Two Factor (pre 1.26)
  • Reference
    • CORS
    • Configuration
    • Data Types
    • Known Limitations
    • Password Hashes

    Writing a Webhook

    Writing a Webhook

    In order to appropriately handle requests from the FusionAuth event, you must build a simple HTTP Webhook that listens for requests from the FusionAuth event system. Your Webhook must be designed to receive to simple HTTP POST requests with a JSON request body. The HTTP request will be sent using a Content-Type header value of application/json.

    Additional headers may be added to the request by adding headers to the Webhook configuration.

    Responses

    Your Webhook must handle the RESTful request described above and send back an appropriate status code. Your Webhook must send back to FusionAuth an HTTP response code that indicates whether or not the event was successfully handled or not. If your Webhook handled the event properly, it must send back an HTTP response status code of 2xx. If there was any type of error or failure, your Webhook must send back a non 2xx HTTP response status.

    Configuration

    Once your Webhook is complete and listening for events, you must configure your Webhook URL in FusionAuth. To add a webhook navigate to Settings → Webhooks. If you have multiple Webhooks configured for a single Application, the transaction setting for the event or the User Action will dictate if FusionAuth will commit the transaction or not.

    Calling FusionAuth APIs In Webhooks

    Some events fire on creation of an entity in FusionAuth, such as user.create. You may want to modify the created entity, but if your webhook tries to modify the newly created object in a webhook handling the create event, the operation will fail. This is due to the fact that the operation occurs in a transaction and has not yet completed when the webhook runs.

    In fact, the created user will not be visible to any other API request until the transaction is committed. The operation fails because the webhook is trying to modify an object that has not yet been completely created and has not yet been committed to persistant storage. Depending upon your transaction configuration for a particular event, FusionAuth may wait until all webhooks have responded before committing the transaction.

    Even if you configure your webhook transaction to not require any webhooks to succeed, it is unlikely your code will operate as intended due to the parallel timing of the requests. The user.create event was not designed to allow a webhook to retrieve and modify the user.

    Here’s a scenario:

    • You have a webhook that catches the user.create event.

    • It extracts the user’s email address.

    • Then it queries a non FusionAuth database and adds a custom user.data.premiumUser field to the FusionAuth user object based on the query results.

    • At user login, the value of the user.data.premiumUser field will be placed into a JWT for other applications to access.

    In this example, you have a few options; which one is best depends on when you need to be able to read from the user.data.premiumUser field.

    • Provide the custom data field at user creation, instead of updating the user via a webhook. This option is the simplest, but may not be possible if users are self registering. In this case, the field is available from the moment the user is created.

    • Review available events and determine if a subsequent event occurs in your workflow. For example, user.registration.create may occur after a user is created. At this point, the user will exist and can be modified. If an event happens repeatedly, make the modification idempotent. In this case, the field is available as soon as the other event fires.

    • Don’t process the data in the webhook. Instead, push the event JSON to a queue and return success. Have a queue consumer pull the data off and update the user.data.premiumUser field. The consumer can retry multiple times if the user object has not yet been fully created, which can happen if there are other webhooks whose completion is required. In this case, the field is available when the consumer finishes.

    While this scenario is most obvious when a user or registration is being created, it applies to all webhooks. The final state of the operation which caused the webhook is not persisted to FusionAuth until after the webhook finishes.

    Example Code

    Here’s a simple example of a Webhook written in Node using Express. In this example, if the event is a user.delete event, this code deletes all of the user’s Todos.

    In this example we are also checking the HTTP Authorization header for an API key. Using an API key or some type of authentication helps secure your Webhook to prevent malicious requests. You can configure the API key via the FusionAuth Web Interface or the API using the Headers of the Webhook configuration.

    Example Webhook
    router.route('/fusionauth-webhook').post((req, res) => {
      const authorization = req.header('Authorization');
      if (authorization !== 'API-KEY') {
        res.status(401).send({
          'errors': [{
            'code': '[notAuthorized]'
          }]
        });
        return;
      }
    
      const request = req.body;
      if (request.event.type === 'user.delete') {
        todo.deleteAll(request.event.user.id)
          .then(() => {
            res.sendStatus(200);
          })
          .catch(function(err) {
            _handleDatabaseError(res, err);
          });
      }
    });

    Feedback

    How helpful was this page?

    See a problem?

    File an issue in our docs repo

    © 2021 FusionAuth
    Subscribe for developer updates