Skip to main content

Getting Started with Auth0 Relationship Sync

note

Auth0 Relationship Sync is currently in Beta, available to a limited set of customers. Don't use it against a production FGA store.

Overview​

This guide walks you through setting up Auth0 Relationship Sync end to end. Here's what you'll do:

  1. Write an FGA authorization model into your store
  2. Create a Sync pipeline by connecting to Auth0 and verifying your credentials
  3. Create a mapping file that tells the pipeline how to transform Auth0 events into FGA tuples
  4. Verify that tuples are syncing by making a change in Auth0 and checking FGA

All the code and configuration snippets you need are provided below. If you already have experience with FGA models and authorization rules, you can move quickly through those steps; if you're new, see the linked reference docs for a deeper dive.

Before you start​

Before setting up Auth0 Relationship Sync, you need:

  • An Auth0 tenant.
  • An FGA store.

Understand the model​

Your FGA model needs a type and relation for the mapping rules to write to. This minimal slice is enough for the example in this guide: adding and removing a user from an organization.

model
schema 1.1

type user

type organization
relations
define member: [user]

This is a minimal slice of the suggested authorization model, which also covers tenant roles and SCIM groups. You can grow into the full model later as you map more events.

Write the model into your FGA store​

Before you can select this model in the setup wizard below, it needs to exist in your FGA store. In the FGA Dashboard, open Model Explorer, paste the model above into the editor panel, and click SAVE. See Managing Models if you're setting up your store for the first time.

Create the pipeline​

In the FGA Dashboard, go to Auth0 Relationship Sync in the sidebar to start the setup wizard and create the Sync pipeline.

01. Name Your Pipeline​

Give the Sync pipeline a friendly name to identify it later.

02. Create a Machine-to-Machine (M2M) Application in Auth0​

In the Auth0 tenant you want to read events from, create a Machine-to-Machine application, authorize it to call the Auth0 Management API with the read:events scope, then enter your Auth0 Tenant Domain and the application's Client ID.

03. Establish Private Key JWT Connection to Auth0 Application​

FGA generates an RSA key pair and shows you the public key as a downloadable PEM certificate. Upload it to Auth0 as a Private Key JWT credential on the same Machine-to-Machine application, then click Verify Connection.

note

FGA imposes no expiration of its own on this key; its validity is entirely governed by the credential's expiration setting on the Auth0 side (Never, From certificate, or a Custom date). Auth0 does not notify you ahead of an upcoming expiry. If you set a Custom date, you're responsible for rotating the key on the Auth0 side before it lapses (see Rotating credentials), otherwise the Sync pipeline will stop authenticating once it passes, with no advance warning from either side.

If verification fails, you'll see a Key validation failed message; download the key again and re-upload it to your Auth0 application. See Troubleshooting if it keeps failing.

Once verified, the wizard finishes and creates the Sync pipeline.

Understand the mapping​

A mapping file is a YAML document that tells the Sync pipeline how to transform Auth0 events into FGA tuples, one rule per event. Here's the smallest version that does something useful: adding and removing a user from an organization.

version: "1"

rules:
- name: "Add user to organization"
when: input.type == "organization.member.added"
variables:
organization_id: input.data.object.organization.id
user_id: input.data.object.user.user_id
tuples:
- user: "user:{{ variables.user_id }}"
relation: "member"
object: "organization:{{ variables.organization_id }}"

- name: "Remove user from organization"
when: input.type == "organization.member.deleted"
variables:
organization_id: input.data.object.organization.id
user_id: input.data.object.user.user_id
tuples:
- action: delete
user: "user:{{ variables.user_id }}"
relation: "member"
object: "organization:{{ variables.organization_id }}"

These rules fire whenever Auth0 emits organization.member.added or organization.member.deleted to write or delete the corresponding tuples.

Add a model and mapping​

The Sync pipeline exists but sits idle until it has a model and mapping. From its Add Mappings to Pipeline page, select the model you wrote into your store above, paste the mapping YAML above into the Mappings field, and click Add Mappings.

FGA validates that your mapping is compatible with the selected model, for example that every relation it writes to actually exists on that model, and returns diagnostic details if it isn't.

Verify it's working​

Confirm the Sync pipeline end to end: start it, trigger a real change in Auth0, then check that the resulting tuple landed in FGA.

1. Start the pipeline​

Back on the pipeline's overview, click Start, now enabled since a mapping exists. You'll be asked to confirm, since this begins processing events immediately.

2. Trigger a change in Auth0​

Add yourself, or a test user, as a member of an organization in your Auth0 tenant; this fires the same organization.member.added event the minimal mapping above maps.

In the Auth0 Dashboard, go to Organizations, select the organization, select the Members view, select Add members → Add Users, enter the user, then select Add user(s) to organization. See Auth0's Assign Members doc for the full flow, including the Management API equivalent.

3. Confirm the tuple landed in FGA​

Before making a change, establish a baseline. Note the exact user ID and organization ID you're about to use (from Auth0), then confirm no tuple exists yet for them:

  • Dashboard: open the FGA Dashboard's Tuple Management page and type the organization's ID (e.g. org456) into the Type to filter tuples... box on the left, under Tuples. This filters the list already loaded on the page; it's a plain substring match, not a query, so a partial ID works too. Don't use the Query Tool box on the right for this; that one only accepts a full sentence like Is user:user123 related to organization:org456 as member? and rejects a bare ID with an "Improper query format" error.
  • CLI: fga tuple read --store-id=<your-store-id> --user user:user123 --object organization:org456. If the user ID contains a pipe character (common for Auth0 IDs, e.g. auth0|abc123), quote it so your shell doesn't treat the | as a pipe operator: --user 'user:auth0|abc123'. The Read API requires an object whenever you filter by user; pass --object organization: (type only, no ID) if you don't have a specific organization ID yet.

Then go back to Auth0 and add the user to the organization. This fires the organization.member.added event, which the Sync pipeline transforms into a tuple.

Within a few seconds, check again with the same method:

  • Dashboard: re-filter the Tuple Management page's tuple list by the organization ID and confirm the new tuple appeared, with your user as the user and member as the relation.
  • CLI: re-run the same fga tuple read command; it should now return the tuple.

Finally, remove the user from the organization in Auth0. This fires organization.member.deleted, and the tuple should disappear within a few seconds; filter or query again to confirm it's gone (the CLI command should return an empty result).

If tuples don't appear or disappear as expected, see Troubleshooting.

Next steps​

You've deployed the minimal model and mapping this guide provides. To map more of your own Auth0 data:

  • Supported Auth0 events — what else you can sync, and known limitations to plan around.
  • Comprehensive template — a ready-to-use mapping covering tenant roles and SCIM groups on top of the organization membership rules above.
  • Mapping Language — the full mapping-file syntax: tuple filters, iterators, the expression language, and embedded tests.
  • Writing a Mapping File — write, validate, and test mappings locally before pasting them into the dashboard.

Have Feedback?

You can use any of our support channels for any questions or suggestions you may have.