Organizations & roles

Clerk’s organizations feature lets users belong to shared workspaces with roles and permissions. ngx-clerk covers it with four prebuilt components, an authorization check on ClerkService, the *clerkProtect directive, and the canActivateProtect guard.

Organization components

Four of the 13 components manage organizations. They mount the same way as every other Clerk component, with no required [props]:

Component Selector Renders
ClerkOrganizationSwitcherComponent clerk-organization-switcher dropdown to switch the active organization or personal account
ClerkOrganizationProfileComponent clerk-organization-profile settings, members, and invitations for the active organization
ClerkCreateOrganizationComponent clerk-create-organization form to create a new organization
ClerkOrganizationListComponent clerk-organization-list every organization the user belongs to, with actions to switch or create
// src/app/dashboard/dashboard-home.component.ts
import { Component } from '@angular/core';
import { ClerkOrganizationSwitcherComponent } from 'ngx-clerk';

@Component({
  selector: 'app-dashboard-home',
  imports: [ClerkOrganizationSwitcherComponent],
  template: `<clerk-organization-switcher />`,
})
export class DashboardHomeComponent {}

ClerkOrganizationProfileComponent, ClerkCreateOrganizationComponent, and ClerkOrganizationListComponent follow the same pattern — <clerk-organization-profile />, <clerk-create-organization />, <clerk-organization-list />. See Components for their full [props] types and path-routing support.

Checking roles, permissions, features, and plans

ClerkService.has() checks the current user’s authorization against the cached session JWT claims — it never makes a network request:

has(params: CheckAuthorizationParams): boolean

CheckAuthorizationParams (exported from ngx-clerk) accepts the same { role | permission | feature | plan } shape used by *clerkProtect and route guards — exactly one of the four:

clerk.has({ role: 'org:admin' });
clerk.has({ permission: 'org:posts:manage' });
clerk.has({ feature: 'user:premium_support' });
clerk.has({ plan: 'org:pro' });

role and permission are evaluated against the active organization — both are false if there’s no active organization, even for a signed-in user. feature and plan are looked up by scope prefix (org: or user:) in the session claims. While signed out, has() always returns false, regardless of the params passed. See Roles and permissions and features and plans for how these are configured in the Clerk Dashboard.

Gate UI with *clerkProtect

*clerkProtect renders its content only when the condition is authorized, with an optional else template for the unauthorized case:

<section *clerkProtect="{ role: 'org:admin' }; else notAdmin">
  You have the <code>org:admin</code> role in the active organization.
</section>
<ng-template #notAdmin>
  You need the <code>org:admin</code> role to see this content.
</ng-template>

See Protecting routes for the predicate form (*clerkProtect="fn") and the rest of the guard reference.

Guard a route by role

canActivateProtect creates a guard from the same CheckAuthorizationParams shape. Unauthenticated users are redirected to sign-in; signed-in-but-unauthorized users are blocked or sent to unauthorizedUrl:

// src/app/app.routes.ts
import { Routes } from '@angular/router';
import { canActivateProtect } from 'ngx-clerk';

export const routes: Routes = [
  {
    path: 'admin',
    canActivate: [canActivateProtect({ role: 'org:admin' }, { unauthorizedUrl: '/dashboard' })],
    loadComponent: () => import('./admin.component').then((m) => m.AdminComponent),
  },
];

Reading organization state

ClerkService exposes the active organization as signals — see Reading auth state for the complete signal table and ClerkService for every method:

Signal Description
organization() the active organization resource, or null if none is active
orgId(), orgSlug() the active organization’s ID and slug
orgRole() the current user’s role in the active organization
membership() the current user’s membership in the active organization — carries .role and .permissions
const clerk = inject(ClerkService);
clerk.orgRole(); // e.g. 'org:admin', or null with no active organization
clerk.membership()?.permissions; // e.g. ['org:posts:manage', …]

Switch the active organization with setActive():

await clerk.setActive({ organization: orgId });

Unofficial, community-maintained · not affiliated with Clerk.com