Jacqui Hurst
Feb 20, 2024Copper Contributor
Invoke-RestMethod Upload a File to Sharepoint 401 error
Hi
Please help. I have tried many different scripts (taken from the Internet and modified) to try and upload a file to a Sharepoint library but I keep leading myself back to the same issue of a 401 error, access denied. The only errors I have in the script are when I use the invoke-restmethod. This occurs on both instances in the script.
One of the scripts is as follows
# Set your SharePoint site URL and library name
$siteUrl = "https://mytenant.sharepoint.com/sites/ITandSoftware"
$libraryName = "Shared Documents"
# Authenticate to Microsoft Graph using the app registration credentials
$clientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$tenantId = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
# Get an access token
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/token"
$body = @{
client_id = $clientId
scope = "https://graph.microsoft.com/.default"
client_secret = $clientSecret
grant_type = "client_credentials"
}
$response = Invoke-RestMethod -Uri $tokenUrl -Method POST -ContentType "application/x-www-form-urlencoded" -Body $body
$accessToken = $response.access_token
# Create a new folder in the library based on the current date
$folderName = (Get-Date).ToString("yyyyMMdd")
$folderUrl = "$siteUrl/_api/web/lists/getbytitle('$libraryName')/rootfolder/folders/add(url='$folderName')"
try {
Invoke-RestMethod -Uri $folderUrl -Method POST -Headers @{Authorization = "Bearer $accessToken"
}
} catch {
# Dig into the exception to get the Response details.
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
}
# Upload a file (modify this part according to your actual data source)
$filePath = "C:\TEMP\Myfilesourcename.csv"
$fileName = "FileName.csv"
$fileUrl = "$siteUrl/_api/web/lists/getbytitle('$libraryName')/rootfolder/files/add(url='$fileName',overwrite=true)"
try {
Invoke-RestMethod -Uri $fileUrl -Method POST -Headers @{Authorization = "Bearer $accessToken"} -InFile $filePath
} catch {
# Dig into the exception to get the Response details.
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
}
I have granted the Application Sharepoint - Sites.Read.All and Site.Read.Write.All and Microsoft Graph - Sites.Read.All and Sites.ReadWrite.All with the API permissions. These have been granted at the admin level. I have checked all my clientsecret etc are correct and I get an access token.
I am at a loss as to what I am missing about granting the correct access or applying my token correctly in my script.
Can anyone help?
Thanks
- I took a step back and started again and after a little more research I found a method that works. I moved away from Client Secret to a certificate and used PNP.Powershell. There is loads of work in getting this running but at least I have an unattended script now.
$tenant = “xxxxxxx”
$url = "https://$tenant.sharepoint.com/sites/ITandSoftware"
$file = "c:\temp\test.txt"
$ClientID = "xxxxxxxxxxxxxx"
$CertThumb = 'xxxxxxxxxxxxxxxxxx'
Connect-PnPOnline $url -ClientId $ClientID -Tenant $tenant.onmicrosoft.com -Thumbprint $CertThumb
Add-PnPFile -folder "Shared Documents/Calls" -path $file
I thought I would share in case anyone wanted to know the conclusion.
Thanks for responses though, it helps to know there is some help out there when needed.