Skip to main content
figma-enterprise-rbac Configure Figma Enterprise features: OAuth 2.0, team management, and access control.
Use when implementing OAuth flows, managing team/project access via API,
or building Enterprise-level Figma integrations.
Trigger with phrases like "figma enterprise", "figma OAuth",
"figma team management", "figma access control", "figma SCIM".
インストールへ移動 Skills Marketplace コミュニティが作成したAIスキルを発見・探索
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill figma-enterprise-rbacコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Zipをダウンロード ダウンロード中... jeremylongshore
jeremylongshore/claude-code-plugins-plus-skills
GitHub リポジトリを開く name figma-enterprise-rbac description Configure Figma Enterprise features: OAuth 2.0, team management, and access control.
Use when implementing OAuth flows, managing team/project access via API,
or building Enterprise-level Figma integrations.
Trigger with phrases like "figma enterprise", "figma OAuth",
"figma team management", "figma access control", "figma SCIM".
allowed-tools Read, Write, Edit version 1.6.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","figma"] compatibility Designed for Claude Code
Figma Enterprise RBAC
Overview
Figma Enterprise features accessible via the REST API: OAuth 2.0 for user-facing apps, team/project management, and the Variables API (Enterprise-only). This skill covers building OAuth integrations and managing organizational access.
Prerequisites
Figma Enterprise or Organization plan
OAuth app registered in Figma developer dashboard
Understanding of OAuth 2.0 authorization code flow
Instructions
Step 1: OAuth 2.0 App Setup
function getAuthUrl (state : string ): string {
const params = new URLSearchParams ({
client_id : process.env .FIGMA_CLIENT_ID !,
redirect_uri : process.env .FIGMA_REDIRECT_URI !,
scope : 'file_content:read,file_comments:write,file_variables:read' ,
state,
response_type : 'code' ,
});
return `https://www.figma.com/oauth?${params} ` ;
}
async function exchangeCode (code : string ): Promise <{
access_token : string ;
refresh_token : string ;
expires_in : number ;
user_id : ;
}> {
res = ( , {
: ,
: { : },
: ({
: process. . !,
: process. . !,
: process. . !,
code,
: ,
}),
});
(!res. ) {
error = res. ();
( );
}
res. ();
}
( ): <{
: ;
: ;
}> {
res = ( , {
: ,
: { : },
: ({
: process. . !,
: process. . !,
: refreshToken,
}),
});
(!res. ) ( );
res. ();
}
string
const
await
fetch
'https://api.figma.com/v1/oauth/token'
method
'POST'
headers
'Content-Type'
'application/x-www-form-urlencoded'
body
new
URLSearchParams
client_id
env
FIGMA_CLIENT_ID
client_secret
env
FIGMA_CLIENT_SECRET
redirect_uri
env
FIGMA_REDIRECT_URI
grant_type
'authorization_code'
if
ok
const
await
text
throw
new
Error
`Token exchange failed: ${res.status} ${error} `
return
json
async
function
refreshAccessToken
refreshToken : string
Promise
access_token
string
expires_in
number
const
await
fetch
'https://api.figma.com/v1/oauth/refresh'
method
'POST'
headers
'Content-Type'
'application/x-www-form-urlencoded'
body
new
URLSearchParams
client_id
env
FIGMA_CLIENT_ID
client_secret
env
FIGMA_CLIENT_SECRET
refresh_token
if
ok
throw
new
Error
`Token refresh failed: ${res.status} `
return
json
Step 2: OAuth Callback Handler
app.get ('/auth/figma/callback' , async (req, res) => {
const { code, state } = req.query ;
if (state !== req.session .oauthState ) {
return res.status (403 ).json ({ error : 'Invalid state parameter' });
}
try {
const tokens = await exchangeCode (code as string );
const userRes = await fetch ('https://api.figma.com/v1/me' , {
headers : { Authorization : `Bearer ${tokens.access_token} ` },
});
const user = await userRes.json ();
await saveUserTokens (user.id , {
accessToken : tokens.access_token ,
refreshToken : tokens.refresh_token ,
expiresAt : new Date (Date .now () + tokens.expires_in * 1000 ),
});
res.redirect ('/dashboard?connected=figma' );
} catch (error) {
console .error ('Figma OAuth error:' , error);
res.redirect ('/settings?error=figma_auth_failed' );
}
});
Step 3: Team and Project Management
async function getTeamProjects (teamId : string , token : string ) {
const res = await fetch (
`https://api.figma.com/v1/teams/${teamId} /projects` ,
{ headers : { Authorization : `Bearer ${token} ` } }
);
return res.json ();
}
async function getProjectFiles (projectId : string , token : string ) {
const res = await fetch (
`https://api.figma.com/v1/projects/${projectId} /files` ,
{ headers : { Authorization : `Bearer ${token} ` } }
);
return res.json ();
}
async function getTeamComponents (teamId : string , token : string ) {
const res = await fetch (
`https://api.figma.com/v1/teams/${teamId} /components` ,
{ headers : { Authorization : `Bearer ${token} ` } }
);
return res.json ();
}
async function getTeamStyles (teamId : string , token : string ) {
const res = await fetch (
`https://api.figma.com/v1/teams/${teamId} /styles` ,
{ headers : { Authorization : `Bearer ${token} ` } }
);
return res.json ();
}
Step 4: Variables API (Enterprise Only)
async function getLocalVariables (fileKey : string , token : string ) {
const res = await fetch (
`https://api.figma.com/v1/files/${fileKey} /variables/local` ,
{ headers : { Authorization : `Bearer ${token} ` } }
);
if (res.status === 403 ) {
throw new Error ('Variables API requires Figma Enterprise plan' );
}
return res.json ();
}
async function getPublishedVariables (fileKey : string , token : string ) {
const res = await fetch (
`https://api.figma.com/v1/files/${fileKey} /variables/published` ,
{ headers : { Authorization : `Bearer ${token} ` } }
);
return res.json ();
}
async function updateVariables (
fileKey : string ,
changes : VariableChanges ,
token : string
) {
const res = await fetch (
`https://api.figma.com/v1/files/${fileKey} /variables` ,
{
method : 'POST' ,
headers : {
Authorization : `Bearer ${token} ` ,
'Content-Type' : 'application/json' ,
},
body : JSON .stringify (changes),
}
);
return res.json ();
}
Step 5: Access Control Middleware
async function requireFigmaAccess (fileKey : string ) {
return async (req : Request , res : Response , next : NextFunction ) => {
const userToken = await getUserFigmaToken (req.user .id );
if (!userToken) {
return res.status (403 ).json ({ error : 'Figma account not connected' });
}
const check = await fetch (
`https://api.figma.com/v1/files/${fileKey} ?depth=1` ,
{ headers : { Authorization : `Bearer ${userToken} ` } }
);
if (check.status === 403 ) {
return res.status (403 ).json ({ error : 'No access to this Figma file' });
}
next ();
};
}
Output
OAuth 2.0 flow with authorization, token exchange, and refresh
Team/project/file listing via API
Variables API access (Enterprise)
Access control middleware for file-level permissions
Error Handling Error Cause Solution OAuth code expired Exchange took >30s Exchange immediately on callback Token refresh failed Refresh token revoked Re-authenticate user through OAuth flow 403 on Variables API Not Enterprise plan Use styles API instead (available on all plans) Team components empty No published components Publish components in Figma first
Examples Complete the OAuth flow locally and inspect the granted user (Steps 1-2):
curl -s -H "Authorization: Bearer ${FIGMA_OAUTH_TOKEN} " https://api.figma.com/v1/me \
| jq '{handle, email}'
List a project's files as that user — RBAC means you only see what the user can (Step 3):
curl -s -H "Authorization: Bearer ${FIGMA_OAUTH_TOKEN} " \
"https://api.figma.com/v1/projects/${PROJECT_ID} /files" | jq '.files[].name'
A 403 here is working access control, not a bug — route it through the Step 5 middleware. Variables API (Enterprise-only) usage: references/variables-api-enterprise-only.md.
Resources
Next Steps For major migrations, see figma-migration-deep-dive.