Back to skills
SKILL.md
Miro Enterprise Rbac
ASecurity'Configure Miro Enterprise features: organization management, SCIM provisioning, board-level access control, audit logs, and SSO integration via REST API v2. Trigger with phrases like \"miro SSO\", \"miro RBAC\", \"miro enterprise\", \"miro SCIM\", \"miro permissions\", \"miro organization\". '
- 3 stars
- 0 votes
- 0 copies
- 3 views
- Added September 12, 2026
Works with
Security analysis
100/100npx -y skills add thedixitjain/the-mega-skill-library --skill miro-enterprise-rbac --agent claude-codeAre you the author of Miro Enterprise Rbac?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/thedixitjain-miro-enterprise-rbac)---
name: miro-enterprise-rbac
description: "'Configure Miro Enterprise features: organization management, SCIM provisioning, board-level access control, audit logs, and SSO integration via REST API v2. Trigger with phrases like \"miro SSO\", \"miro RBAC\", \"miro enterprise\", \"miro SCIM\", \"miro permissions\", \"miro organization\". '"
allowed-tools: "Read, Write, Edit"
category: backend-and-data
source_repo: jeremylongshore/claude-code-plugins-plus-skills
source_path: "plugins/saas-packs/miro-pack/skills/miro-enterprise-rbac/SKILL.md"
source_url: https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/HEAD/plugins/saas-packs/miro-pack/skills/miro-enterprise-rbac/SKILL.md
---
# Miro Enterprise RBAC
## Overview
Enterprise-grade access control for Miro REST API v2: organization and team management, SCIM user provisioning, board sharing with role-based permissions, and audit log access. Requires Miro Enterprise plan.
## Miro Access Hierarchy
```
Organization (Enterprise)
├── Team 1
│ ├── Board A (sharing: team only)
│ │ ├── Owner (full control)
│ │ ├── Co-owner (full control, can't delete board)
│ │ ├── Editor (can add/edit items)
│ │ ├── Commenter (can add comments only)
│ │ └── Viewer (read-only)
│ └── Board B
├── Team 2
│ └── Board C
└── Projects
└── Project 1 (groups boards)
```
## Board Roles & Permissions
| Role | View | Comment | Edit Items | Share | Delete Board |
|------|------|---------|------------|-------|-------------|
| Viewer | Yes | No | No | No | No |
| Commenter | Yes | Yes | No | No | No |
| Editor | Yes | Yes | Yes | No | No |
| Co-owner | Yes | Yes | Yes | Yes | No |
| Owner | Yes | Yes | Yes | Yes | Yes |
## Board Member Management
```typescript
// List board members
// GET https://api.miro.com/v2/boards/{board_id}/members
const members = await miroFetch(`/v2/boards/${boardId}/members?limit=50`);
for (const member of members.data) {
console.log(`${member.name} (${member.id}): role=${member.role}`);
}
// Share board with users
// POST https://api.miro.com/v2/boards/{board_id}/members
await miroFetch(`/v2/boards/${boardId}/members`, 'POST', {
emails: ['dev@company.com', 'pm@company.com'],
role: 'editor', // 'viewer' | 'commenter' | 'editor' | 'coowner'
message: 'You have been added to the sprint board',
});
// Update member role
// PATCH https://api.miro.com/v2/boards/{board_id}/members/{member_id}
await miroFetch(`/v2/boards/${boardId}/members/${memberId}`, 'PATCH', {
role: 'commenter',
});
// Remove member from board
// DELETE https://api.miro.com/v2/boards/{board_id}/members/{member_id}
await miroFetch(`/v2/boards/${boardId}/members/${memberId}`, 'DELETE');
```
## Team Management (Enterprise)
```typescript
// List teams in organization
// GET https://api.miro.com/v2/orgs/{org_id}/teams (Enterprise)
const teams = await miroFetch(`/v2/orgs/${orgId}/teams?limit=50`);
// Get team details
// GET https://api.miro.com/v2/teams/{team_id}
const team = await miroFetch(`/v2/teams/${teamId}`);
// List team members
// GET https://api.miro.com/v2/teams/{team_id}/members
const teamMembers = await miroFetch(`/v2/teams/${teamId}/members?limit=100`);
// Invite user to team
// POST https://api.miro.com/v2/teams/{team_id}/members
await miroFetch(`/v2/teams/${teamId}/members`, 'POST', {
emails: ['newdev@company.com'],
role: 'member', // 'member' | 'admin' | 'non_team'
});
```
## Organization Management (Enterprise)
```typescript
// Get organization info
// GET https://api.miro.com/v2/orgs/{org_id}
const org = await miroFetch(`/v2/orgs/${orgId}`);
// List organization members
// GET https://api.miro.com/v2/orgs/{org_id}/members
const orgMembers = await miroFetch(`/v2/orgs/${orgId}/members?limit=100`);
```
## SCIM User Provisioning (Enterprise)
Miro supports SCIM 2.0 for automated user lifecycle management from identity providers (Okta, Azure AD, OneLogin).
```typescript
// SCIM Base URL: https://miro.com/api/v1/scim/v2
// Create user via SCIM
// POST https://miro.com/api/v1/scim/v2/Users
const scimUser = await fetch('https://miro.com/api/v1/scim/v2/Users', {
method: 'POST',
headers: {
'Authorization': `Bearer ${scimToken}`,
'Content-Type': 'application/scim+json',
},
body: JSON.stringify({
schemas: ['urn:ietf:params:scim:schemas:core:2.0:User'],
userName: 'newuser@company.com',
name: { givenName: 'New', familyName: 'User' },
emails: [{ value: 'newuser@company.com', type: 'work', primary: true }],
active: true,
}),
});
// List users via SCIM
// GET https://miro.com/api/v1/scim/v2/Users
const users = await fetch('https://miro.com/api/v1/scim/v2/Users?filter=active eq true', {
headers: { 'Authorization': `Bearer ${scimToken}` },
});
// Deactivate user (deprovision)
// PATCH https://miro.com/api/v1/scim/v2/Users/{user_id}
await fetch(`https://miro.com/api/v1/scim/v2/Users/${scimUserId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${scimToken}`,
'Content-Type': 'application/scim+json',
},
body: JSON.stringify({
schemas: ['urn:ietf:params:scim:api:messages:2.0:PatchOp'],
Operations: [{ op: 'replace', path: 'active', value: false }],
}),
});
// Manage team membership via SCIM Groups
// GET https://miro.com/api/v1/scim/v2/Groups
// POST/PATCH Groups to add/remove team members
```
## Board Sharing Policies
Control how boards can be shared at creation time:
```typescript
// Create board with restrictive sharing
await miroFetch('/v2/boards', 'POST', {
name: 'Confidential Strategy Board',
policy: {
sharingPolicy: {
access: 'private', // Only invited members
inviteToAccountAndBoardLinkAccess: 'no_access',
organizationAccess: 'private', // Not visible to org
teamAccess: 'private', // Not visible to team
},
permissionsPolicy: {
collaborationToolsStartAccess: 'all_editors',
copyAccess: 'team_members', // Only team can copy
sharingAccess: 'owners_and_coowners', // Only owners can share
},
},
});
// Create board with open team access
await miroFetch('/v2/boards', 'POST', {
name: 'Team Brainstorming',
teamId: teamId,
policy: {
sharingPolicy: {
access: 'edit', // Team can edit by default
teamAccess: 'edit',
},
permissionsPolicy: {
sharingAccess: 'team_members_and_collaborators',
},
},
});
```
## Audit Logs (Enterprise)
```typescript
// Get audit logs — requires 'auditlogs:read' scope
// GET https://api.miro.com/v2/orgs/{org_id}/audit-logs
const logs = await miroFetch(
`/v2/orgs/${orgId}/audit-logs?limit=100&createdAfter=${startDate}`
);
// Log entries include:
// - User actions (board created, item modified, member added)
// - Admin actions (team created, user deactivated, settings changed)
// - API actions (OAuth token issued, SCIM provisioning)
for (const entry of logs.data) {
console.log({
action: entry.action,
actor: entry.actor?.email,
target: entry.context?.boardId ?? entry.context?.teamId,
timestamp: entry.createdAt,
});
}
```
## Access Control Middleware
Enforce board-level permissions in your application:
```typescript
type BoardRole = 'viewer' | 'commenter' | 'editor' | 'coowner' | 'owner';
const ROLE_HIERARCHY: Record<BoardRole, number> = {
viewer: 0,
commenter: 1,
editor: 2,
coowner: 3,
owner: 4,
};
function hasMinimumRole(userRole: BoardRole, requiredRole: BoardRole): boolean {
return ROLE_HIERARCHY[userRole] >= ROLE_HIERARCHY[requiredRole];
}
async function requireBoardRole(boardId: string, userId: string, minRole: BoardRole) {
const members = await miroFetch(`/v2/boards/${boardId}/members?limit=100`);
const user = members.data.find((m: any) => m.id === userId);
if (!user) {
throw new Error('User is not a board member');
}
if (!hasMinimumRole(user.role, minRole)) {
throw new Error(`Requires ${minRole} role, user has ${user.role}`);
}
}
// Usage
await requireBoardRole(boardId, userId, 'editor');
// Throws if user doesn't have editor or higher role
```
## Required OAuth Scopes
| Feature | Required Scope |
|---------|---------------|
| Board members | `boards:read` (list) / `boards:write` (manage) |
| Team management | `team:read` / `team:write` |
| Organization | `organizations:read` |
| Audit logs | `auditlogs:read` |
| SCIM provisioning | SCIM token (separate from OAuth) |
## Error Handling
| Error | Status | Cause | Solution |
|-------|--------|-------|----------|
| `insufficientPermissions` | 403 | Missing scope | Add required scope in app settings |
| `memberNotFound` | 404 | User not on board | Invite user first |
| `teamNotFound` | 404 | Wrong team ID or no access | Verify org/team hierarchy |
| `orgNotFound` | 404 | Not Enterprise plan | Upgrade to Enterprise |
| `scimTokenInvalid` | 401 | Wrong SCIM token | Generate new token in admin console |
## Resources
- [Miro Board Members](https://developers.miro.com/docs/rest-api-reference-guide)
- [Permission Scopes](https://developers.miro.com/reference/scopes)
- [SCIM API Introduction](https://developers.miro.com/reference/scim-introduction)
- [Teams API Guide](https://developers.miro.com/docs/teams-api-securely-manage-boards-teams-at-scale)
- [SCIM Groups (Teams)](https://developers.miro.com/docs/groups)
## Next Steps
For major migrations, see `miro-migration-deep-dive`.
---
**Source:** [`jeremylongshore/claude-code-plugins-plus-skills`](https://github.com/jeremylongshore/claude-code-plugins-plus-skills) → `plugins/saas-packs/miro-pack/skills/miro-enterprise-rbac/SKILL.md`
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.