NashTech Blog

Authenticating to SharePoint using app client ID and secret

Table of Contents

Introduction

You’re now ready to build SharePoint file access through your Azure Function or MCP tool. This guide will walk you through authenticating with Client ID and Secret, while ensuring your App Registration has scoped, limited access to only the required SharePoint site

  1. The Challenge: Why traditional authentication doesn’t work for service-to-service scenarios
  2. The Solution: Setting up Azure AD app registration with client credentials
  3. The Implementation: Running PowerShell scripts to grant site permissions
  4. The Cleanup: Revoking access when you’re done

Prerequisites: Azure subscription, SharePoint site, admin permissions


The Problem: Service-to-Service Authentication

You’ve built an Azure Function or Model Context Protocol (MCP) tool that needs to read/write files to SharePoint. You try the obvious approaches:

# ❌ This won't work for automated services
ctx = ClientContext(site_url).with_user_credentials(username, password)

Why this fails:

  • No interactive login: Azure Functions run unattended—no one’s there to type credentials
  • Security risk: Storing user passwords in environment variables is a compliance nightmare
  • MFA breaks it: Modern organizations require multi-factor authentication
  • Token expiration: User sessions expire, causing random failures

You need application-level authentication that works without human intervention.


The Solution: Azure AD Application with Client Credentials

Instead of using a user account, we’ll create an Azure AD application identity with its own credentials.

Key Components:

  • Client ID: Public identifier for your application (like a username)
  • Client Secret: Password for your application (never commit to Git!)
  • Tenant ID: Your organization’s Azure AD identifier
  • Site Permissions: Explicitly granted access to specific SharePoint sites

Step-by-Step Implementation

Phase 1: Create Azure AD Application (5 minutes)

1. Navigate to Azure Portal

Azure Portal → Azure Active Directory → App registrations → + New registration

2. Register Your Application

FieldValue
NameSharePoint Integration App
Supported account typesSingle tenant
Redirect URILeave blank

Click Register and save these values:

Application (client) ID: yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
Directory (tenant) ID:   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

3. Configure API Permissions

Add these Microsoft Graph permissions:

Application Permissions (for service-to-service):

  • Sites.Selected – Access specific sites (recommended)

Delegated Permissions (for user context):

  • email – User email address
  • offline_access – Refresh tokens
  • openid – Sign-in capability
  • profile – Basic user info

4. Grant Admin Consent

⚠️ Critical: Click “Grant admin consent for [Your Organization]”

Without this, your app won’t have actual permissions—just requests for them.

app registration – API permissions

5. Create Client Secret

Certificates & secrets → + New client secret
Description: "SharePoint Access Key"
Expires: 180 days (recommended for production)

🔐 SAVE THE SECRET VALUE IMMEDIATELY – you can’t retrieve it later!

App registration – secrets
Client Secret: abc~xyz789EXAMPLE_DoNotCommitThisToGit...

Phase 2: Grant Site-Level Permissions

Now that your Azure AD app exists, you need to explicitly grant it access to your SharePoint site.

Why this step?Even with Sites.Selected permission, Azure AD doesn’t know which sites to allow. This is the “allow list” step.

1. Download PowerShell Scripts

Clone this repository or download the scripts:

git clone https://github.com/nashtech-garage/SharePoint-permission.git

2. Edit Configuration

Open grant-access.bat and update:

SET TenantId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
SET SiteUrl=https://contoso.sharepoint.com/sites/your-site
SET AppId=yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
SET Permission=write

3. Run Grant Script

.\grant-access.bat

What happens:

  1. PowerShell opens a browser for admin authentication
  2. You sign in with your admin account
  3. Script resolves the SharePoint site ID
  4. Grants the specified permission to your app
  5. Confirms success

Expected output:

========================================
SharePoint Site Permission Grant Tool
========================================
Tenant ID:    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Site URL:     https://contoso.sharepoint.com/sites/your-site
App ID:       yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
Permission:   write

*** IMPORTANT NOTE ***
This script grants SITE-LEVEL permissions, which apply to ALL libraries in the site.
========================================

Connecting to Microsoft Graph...
Successfully connected to tenant.

Resolving SharePoint site...
Site Name: Your Site
Site ID:   contoso.sharepoint.com,abc123,def456

Granting site-level permission...
SUCCESS: Granted write permission to site
This permission applies to ALL libraries in the site
========================================
Permission grant process completed!
========================================

4. Verify Permissions

Run the check script to confirm:

.\check-access.bat

You should see your app listed with the granted roles.


Phase 3: Use in Your Application

Azure Function Example (Python):

import os
from office365.sharepoint.client_context import ClientContext
from office365.runtime.auth.client_credential import ClientCredential

# Load from environment variables or Azure Key Vault
tenant_id = os.getenv('AZURE_TENANT_ID')
client_id = os.getenv('AZURE_CLIENT_ID')
client_secret = os.getenv('AZURE_CLIENT_SECRET')
site_url = os.getenv('SHAREPOINT_SITE_URL')

# Authenticate using client credentials
credentials = ClientCredential(client_id, client_secret)
ctx = ClientContext(site_url).with_credentials(credentials)

# Access SharePoint
web = ctx.web.get().execute_query()
print(f"✅ Connected to: {web.title}")

# Upload a file
folder = ctx.web.get_folder_by_server_relative_url("/sites/your-site/Shared Documents")
with open("report.pdf", "rb") as f:
    folder.upload_file("report.pdf", f.read()).execute_query()
print("✅ File uploaded successfully")

MCP Tool Example (Configuration):

{
  "mcpServers": {
    "sharepoint": {
      "command": "python",
      "args": ["-m", "sharepoint_mcp"],
      "env": {
        "AZURE_TENANT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "AZURE_CLIENT_ID": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
        "AZURE_CLIENT_SECRET": "abc~xyz789...",
        "SHAREPOINT_SITE_URL": "https://contoso.sharepoint.com/sites/your-site"
      }
    }
  }
}

Azure Function Configuration (App Settings):

AZURE_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AZURE_CLIENT_ID=yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy
AZURE_CLIENT_SECRET=@Microsoft.KeyVault(SecretUri=https://your-vault.vault.azure.net/secrets/SharePointSecret/)
SHAREPOINT_SITE_URL=https://contoso.sharepoint.com/sites/your-site

💡 Pro tip: Use Azure Key Vault for secrets in production—never hardcode them!


Important Limitations & Workarounds

⚠️ Site-Level vs Library-Level Permissions

The Limitation:Microsoft Graph API only supports site-level permissions for applications. You cannot grant access to specific libraries.

What this means:

  • Permission applies to ALL libraries in the site
  • No way to restrict app to “Documents” library only
  • Graph API doesn’t expose library-granular controls

The Workaround:Implement access control in your application code:

# config.py
ALLOWED_LIBRARIES = ["Documents", "Reports", "Assets"]

# sharepoint_service.py
def validate_library_access(library_name: str):
    if library_name not in ALLOWED_LIBRARIES:
        raise PermissionError(f"Access denied to library: {library_name}")
    # Proceed with operation

Alternative Architecture:

  • Use separate SharePoint sites for strict isolation
  • Grant app access only to the sites it needs
  • One app per site if maximum security is required

Troubleshooting Common Issues

🔴 Error: “Application does not have permission to access this site”

Cause: Site permission not granted via scripts.

Fix:

# Re-run grant script
.\grant-library-access.ps1 -TenantId "..." -SiteUrl "..." -AppId "..." -Permission "write"

🔴 Error: “Client secret has expired”

Cause: Secrets expire after the configured period (180 days, 1 year, etc.).

Fix:

  1. Azure Portal → App registrations → Your app → Certificates & secrets
  2. Delete expired secret
  3. Create new secret
  4. Update environment variables/Key Vault
  5. Restart your application

Prevention:Set calendar reminders 30 days before expiration.


🔴 Error: “Insufficient privileges to complete the operation”

Cause: Admin consent not granted in Azure Portal.

Fix:

  1. Azure Portal → App registrations → Your app → API permissions
  2. Click “Grant admin consent for [Your Organization]”
  3. Verify green checkmarks appear
  4. Wait 5 minutes for propagation
  5. Retry

🔴 Error: “Site not found” in PowerShell script

Cause: Incorrect Site URL format.

Fix:

✅ Correct: https://contoso.sharepoint.com/sites/demo
❌ Wrong:   https://contoso.sharepoint.com/sites/demo/
❌ Wrong:   https://contoso.sharepoint.com/sites/demo/Shared%20Documents

Cleanup: Revoking Access When Done

When your project ends or you no longer need SharePoint access:

Option 1: Revoke Site Permissions (Keep App)

Use this if you want to keep the Azure AD app but remove SharePoint access:

.\revoke-access.bat

What happens:

  • Script finds all permissions for your app
  • Shows what will be deleted
  • Asks for “YES” confirmation
  • Removes site-level permissions via Graph API

Result: App still exists in Azure AD but can’t access SharePoint.


Option 2: Delete Azure AD Application (Complete Cleanup)

Use this for complete removal:

Delete via Azure Portal:
Azure Portal → App registrations → Your app → Delete → Confirm

Result: App and all its permissions are permanently deleted.


Real-World Use Cases

✅ Document Processing Pipeline

Scenario: MCP tool monitors SharePoint folder, extracts text from PDFs, indexes in Azure AI Search.

Benefits:

  • Automatic content indexing
  • Enhanced search capabilities
  • RAG-powered chatbots
  • Compliance document analysis

✅ Multi-Site Data Aggregation

Scenario: Azure Function accesses SharePoint sites, consolidates data into central dashboard.

Benefits:

  • Single view of distributed data
  • Cross-site analytics
  • Centralized reporting
  • Reduced manual data gathering

Key Takeaways

Client ID + Secret authentication enables secure, automated access to SharePoint without user login
Permissions can be scoped to a single SharePoint site, ensuring least-privilege access
Setup takes ~15–20 minutes to register the Azure AD app and configure access
More secure than user passwords, suitable for production workloads
Fully automated workflows—no human involvement required after setup
Easily revocable by disabling secret or removing access when no longer needed

Next Steps

  1. Implement library-level access control in your application
  2. Set up Azure Key Vault for secret storage
  3. Enable Application Insights for monitoring
  4. Configure automated secret rotation

Additional Resources

Picture of ledangchaupha

ledangchaupha

Leave a Comment

Suggested Article

Discover more from NashTech Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading