Skip to main content

Step 5 — Roles and SSO

The CRM works but every user is admin. Real applications have at least two profiles — operators who edit, viewers who read — and increasingly they sign in via the company's identity provider (Authentik, Keycloak, Azure AD, Okta) instead of a per-app password.

This step splits the CRM into three roles and adds OIDC sign-in. Estimated time: 15 minutes.


What we're doing and why

The framework's access-control model has two halves:

HalfWhere it lives
What can be done — atomic permission codes generated automatically per query, screen, dashboard, job.The codes appear in the Permissions tab of every builder. We don't type them.
Who can do it — roles that group permissions, assigned to users.Settings → Roles + Settings → Users.

The split lets us define roles once and assign them to many users, without ever touching individual permission codes by hand.

For the CRM we'll set up three roles:

RoleWhat they can do
crm-viewerSee the dashboard and the screens, but no edit.
crm-salesRead + write everything on customers, deals, activities.
crm-adminSame as crm-sales + access to the Settings UI.

Then we'll add an OIDC backend so users sign in with the company IdP.


Look at the permission codes you already have

Open Settings → Connectors → customers → Permissions tab. You see the four codes that the connector generated automatically:

CodeGenerated for
sql:customers:listThe read query.
sql:customers:create:writeThe insert.
sql:customers:update:writeThe update.
sql:customers:delete:writeThe delete.

Same for deals and activities. Plus a few that came from the dashboard and the menu:

CodeGenerated for
screen:crm:customersVisiting the Customers screen (page-level gate).
screen:crm:dealsSame for Deals.
dashboard:crm-pipeline-overviewThe dashboard.
menu:crm:*The leaves of the crm menu.

The framework gives us wildcardssql:customers:* covers every customer query, screen:crm:* covers every CRM screen. We'll use wildcards for the role definitions.


Define crm-viewer

Settings → Roles → + New role:

FieldValue
Idcrm-viewer
Display nameCRM viewer
DescriptionRead-only access to CRM screens and the pipeline dashboard.

In the Permissions granted section, click + Add permission and add the codes that match read-only access:

CodeWhat it grants
sql:customers:listRead customers.
sql:deals:* (wildcard)Read all deal queries — including the aggregates that feed the dashboard. We don't add the :write codes.
sql:activities:listRead activities.
screen:crm:customersVisit the Customers screen.
screen:crm:dealsVisit the Deals screen.
dashboard:crm-pipeline-overviewVisit the dashboard.
menu:crm:*See the CRM workspace + every leaf in it. The screens / dashboards themselves are gated; a leaf without permission for its target is hidden anyway.
chart:crm-pipeline-by-stageSee the chart (otherwise the panel disappears).

Save.

A read-only crm-viewer is now possible. Since they don't carry any :write codes, the framework renders every screen in read-only mode — Add / Edit / Delete buttons hidden, dialog opens in view mode.


Define crm-sales

+ New role again:

FieldValue
Idcrm-sales
Display nameCRM sales
DescriptionFull read + write access to customers, deals and activities.
Inherits fromcrm-viewer

By inheriting from crm-viewer we get every read code for free; we just need to add the writes:

CodeWhat it grants
sql:customers:create:write
sql:customers:update:write
sql:customers:delete:write
sql:deals:create:write
sql:deals:update:write
sql:deals:delete:write
sql:activities:create:write
sql:activities:delete:write

Save.


Define crm-admin

FieldValue
Idcrm-admin
Display nameCRM admin
Inherits fromcrm-sales
CodeWhat it grants
settings:readThe Settings link appears in the header.
settings:connectorsEdit connectors.
settings:screensEdit screens.
settings:menusEdit menus.
settings:dashboardsEdit dashboards.
settings:chartsEdit charts.
settings:dictionaryEdit dictionary.
settings:reloadThe Save & reload button works.
users:read + users:writeManage users (we'll need this when OIDC creates new users).

Note we deliberately don't give settings:framework or settings:raw — those are for the platform admin user only.

Save.


Create two users to test

Settings → Users → + New user:

UserRoles
sales-alicecrm-sales
viewer-bobcrm-viewer

Set a password for each, then sign out of admin and sign in as sales-alice. You should see:

  • Workspace selector shows CRM (the only workspace Alice can see).
  • Pipeline overview, Customers, Deals in the sidebar.
  • Edit / Add / Delete buttons present.
  • No Settings link in the header.

Sign in as viewer-bob:

  • Same three sidebar entries (he can see them).
  • Edit / Add / Delete buttons hidden — the screens render read-only.
  • Clicking a row opens the dialog in view mode (no Save button).
  • Trying to type /settings in the URL → 403.

The framework's pruning is silent: nothing says "you can't do this", the controls simply aren't there.


Wire OIDC sign-in

OIDC turns the company's identity provider into Liberty's authentication backend. Users sign in once, single sign-out, central audit. We'll set it up against Authentik as the example — the procedure is identical for Keycloak, Azure AD, Okta.

On Authentik

  1. Create an OAuth2/OpenID Provider in Authentik's admin.
  2. Set the Redirect URI to http://127.0.0.1:8000/auth/oidc/callback (production: the real public URL).
  3. Note the Client ID + Client secret that Authentik generates.
  4. Create an Application linked to the provider; pick the groups to surface in the token (we'll map them to Liberty roles).

On Liberty

Open Settings → Framework → Authentication and flip OIDC enabled on. Fill in:

FieldValue
Issuer URLhttps://auth.example.com/application/o/liberty/ (trailing slash matters in Authentik)
Client IDthe Authentik client id
Client secret🔒 the Authentik client secret (stored encrypted)
Redirect URIhttp://127.0.0.1:8000/auth/oidc/callback
Email claimemail
Groups claimgroups
Auto-provision(creates the Liberty user on first SSO sign-in)

Click the ▶ Test sign-in button. A new browser tab opens, Authentik's login page appears, you authenticate, the tab returns "OIDC test successful" plus the resolved claims (email, groups) so you can confirm the mapping is right.

Save & reload.

Map IdP groups to Liberty roles

The framework maps the groups_claim 1:1 to Liberty role identifiers. So an Authentik group named crm-sales becomes the Liberty role crm-sales we already defined. Make sure the names match — that's the whole mapping configuration.

Sign out as admin. The login page now shows a Sign in with SSO button next to the username/password form. Click it, authenticate against Authentik, and you return to the framework with whatever roles the IdP group claim resolved to.

If Auto-provision is on (it is), users who SSO in for the first time are created on the spot with the right roles. No pre-registration needed.


Two things to know about OIDC

ThingWhy it matters
The local backend stays available.The username/password form still works for the admin user. Useful when the IdP is down — you can break-glass into Liberty without depending on Authentik being reachable.
The IdP groups are the source of truth.If you remove a user from the crm-sales group in Authentik, their next sign-in lands them without crm-sales. The user record stays in Liberty (with no roles); the IdP decides who has access.

What you have now

The CRM has real roles, real users, real SSO. Two operator profiles see different things; a manager who only browses gets a read-only experience by construction.

The last layer to add: AI access to the data and a nightly job that keeps the pipeline honest by flagging stale deals.

Step 6 — AI assistant and scheduled jobs.