Forum Discussion
Fabric APIs from notebook using SPN auth
Hi,
I need to call Fabric APIs from notebook to get workspace, items and create shortcuts but getting following error just for shortcut creation.
'errorCode': 'InsufficientScopes', 'message': 'The caller does not have sufficient scopes to perform this operation'
The notebook owner is SPN as it is deployed through fabric ci-cd python library.
I tried following scopes but nothing worked for shortcut creation.
token_string = mssparkutils.credentials.getToken("pbi")
Similarly getting error while retrieving connections /v1/connections.
I noticed if I explicitly get token through ClientSecretCredential class and it worked fine to create shortcuts.
Thanks,
Gayatri
- Anonymous1 year ago
Hi g3kuser ,
As you're building a generic framework that should work for both named users and SPNs, but you're hitting limitations where:>>Direct use of ClientSecretCredential works for SPNs.>>mssparkutils.credentials.getToken(...) does not work for some endpoints (e.g., shortcut creation, connections) under SPN context.Cause for the issue might be,The token retrieved using mssparkutils.credentials.getToken(...) does not always include all required scopes — particularly for application-level permissions used by SPNs. It's likely retrieving a user-delegated token, or a token with limited/default scopes.This mismatch causes InsufficientScopes errors on more privileged Fabric APIs like:*POST /v1/workspaces/{workspaceId}/shortcuts*GET /v1/connectionsThese often require app-level roles and proper access tokens issued via the client credentials flow.We can suggest that,Since you want a framework-agnostic approach, here’s how you can proceed:**Differentiate Named User vs SPN ExecutionUse this logic to detect if the notebook is running under a user or an SPN:try:user = mssparkutils.env.getUserName()is_spn = Falseexcept:is_spn = Trueelse, you can check the structure of the returned token or decode the JWT to see if it’s an app (SPN) or user principal.Split Authentication Flow Dynamicallyif is_spn:# Use explicit credential (ClientSecretCredential) for SPNcredential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)access_token = credential.get_token(scope)token_string = access_token.tokenelse:# Use mssparkutils for user contexttoken_string = mssparkutils.credentials.getToken("https://api.fabric.microsoft.com/.default")This ensures the right token with correct scopes is used based on the execution context.If these workarounds don't help you,I suggest reaching out to Microsoft Support by raising a ticket. Microsoft will analyze backend logs and provide a resolutionBelow is the link to create Microsoft support ticket:If this post helps, then please consider Accepting as solution to help the other members find it more quickly, don't forget to give a "Kudos" – I’d truly appreciate it!
Regards,
B Manikanteswara Reddy
4 Replies
- AnonymousNot applicable
Hi g3kuser ,
Thank you for reaching out to Microsoft Fabric Community Forum.
Since the notebook is being executed under a Service Principal (SPN), you'll need to ensure the app registration in Azure AD is correctly configured for the required permissions.
--Register the SPN (app) in Azure Active Directory, and assign the necessary API permissions for Microsoft Fabric.
--Recommended application-level permissions:
Tenant.Read.All
Workspace.ReadWrite.All
Shortcut.Create.All (if available)
--If you’re using the client credentials flow, you can also work with the /.default scope to inherit all granted permissions.
--After adding the permissions, make sure an Azure AD Admin grants admin consent to them.
Then, you can authenticate using the ClientSecretCredential as follows:
scope = 'https://api.fabric.microsoft.com/.default'
credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)
access_token = credential.get_token(scope)
token_string = access_token.tokenThis approach ensures that your Service Principal has the correct permissions to perform operations like creating shortcuts or managing connections through the Fabric APIs.
If this post helps, then please consider Accepting as solution to help the other members find it more quickly, don't forget to give a "Kudos" – I’d truly appreciate it!Regards,
B Manikanteswara Reddy
- g3kuserHelper II
My app is granted correct permission and I can make the calls successul by explicitly initializing credential object but it fails when only for few endpoints when I don't initialize and get token through mssparkutils.
token_string = mssparkutils.credentials.getToken("pbi")
I don't want to initialize credential class explicilty as I am trying to develop a framework wherein if executed by named user/SPN it should generate the same results.I also tried to identify executing user in notebook using mssparkutils.env.getUserName which returns entire email of named user but in case of SPN as executing user it fails. Atleast if I find a way to differentiate then I split the flow as needed.Thanks,Gayatri- AnonymousNot applicable
Hi g3kuser ,
As you're building a generic framework that should work for both named users and SPNs, but you're hitting limitations where:>>Direct use of ClientSecretCredential works for SPNs.>>mssparkutils.credentials.getToken(...) does not work for some endpoints (e.g., shortcut creation, connections) under SPN context.Cause for the issue might be,The token retrieved using mssparkutils.credentials.getToken(...) does not always include all required scopes — particularly for application-level permissions used by SPNs. It's likely retrieving a user-delegated token, or a token with limited/default scopes.This mismatch causes InsufficientScopes errors on more privileged Fabric APIs like:*POST /v1/workspaces/{workspaceId}/shortcuts*GET /v1/connectionsThese often require app-level roles and proper access tokens issued via the client credentials flow.We can suggest that,Since you want a framework-agnostic approach, here’s how you can proceed:**Differentiate Named User vs SPN ExecutionUse this logic to detect if the notebook is running under a user or an SPN:try:user = mssparkutils.env.getUserName()is_spn = Falseexcept:is_spn = Trueelse, you can check the structure of the returned token or decode the JWT to see if it’s an app (SPN) or user principal.Split Authentication Flow Dynamicallyif is_spn:# Use explicit credential (ClientSecretCredential) for SPNcredential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)access_token = credential.get_token(scope)token_string = access_token.tokenelse:# Use mssparkutils for user contexttoken_string = mssparkutils.credentials.getToken("https://api.fabric.microsoft.com/.default")This ensures the right token with correct scopes is used based on the execution context.If these workarounds don't help you,I suggest reaching out to Microsoft Support by raising a ticket. Microsoft will analyze backend logs and provide a resolutionBelow is the link to create Microsoft support ticket:If this post helps, then please consider Accepting as solution to help the other members find it more quickly, don't forget to give a "Kudos" – I’d truly appreciate it!
Regards,
B Manikanteswara Reddy