Reputation: 1230
I am trying to access SharePoint online Rest API using Azure AD.
I have registered App in Azure AD and Granted full access as described in this Question
After Research, I came to know that I will be able to call SharePoint Rest APIs by Client ID and Certificate.
I uploaded an SSL Certificate along with my App in Azure AD.
Now I want to get That certificate and call SharePoint Rest Api.
I am using the following code to do that by following this Article:
public OverduePOs GetItemDetail(string ItemID, string accessToken)
{
try
{
Uri uri = new Uri(MasterData.SiteURL);
using (var client = new SPHttpClient(uri, MasterData.UserID, MasterData.PWD))
{
var listTitle = "Overdue POs List";
var itemPayload = new { __metadata = new { type = "SP.Data.Overdue_x0020_POs_x0020_ListListItem" } };
var endpointUrl = string.Format("{0}/_api/web/lists/getbytitle('{1}')/items({2})", uri, listTitle, ItemID);
var keyValues = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Authorization", "Bearer "+accessToken)
};
CertificateAuthentication obj_cer = new CertificateAuthentication();
HttpContent content = new FormUrlEncodedContent(keyValues);
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("X-ARR-ClientCert", obj_cer.GetCertificate(MasterData.clientId, "35E646884017E739A7B4F63675886FFB1CEF3C96").GetHashCode().ToString());
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); // Specify JSON format
var response = httpClient.GetAsync(endpointUrl).Result;
var result = response.Content.ReadAsStringAsync().Result;
var test = JsonConvert.DeserializeObject<OverduePOs>(result.ToString());
return JsonConvert.DeserializeObject<OverduePOs>(result.ToString());
}
}
catch (HttpRequestException ex)
{
return null;
}
}
public class CertificateAuthentication
{
public ClientAssertionCertificate GetCertificate(string clientId, string thumbprint)
{
var certificate = GetCertificateFromStore(thumbprint);
return new ClientAssertionCertificate(clientId, certificate);
}
//private static X509Certificate2 GetCertificateFromDirectory(string path, string password)
//{
// return new X509Certificate2(System.IO.Path.GetFullPath(path), password, X509KeyStorageFlags.MachineKeySet);
//}
private static X509Certificate2 GetCertificateFromStore(string thumbprint)
{
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
store.Close();
return certificates[0];
}
}
I have successfully got the Access Token but unable to get the certificate which is required to call SharePoint Rest API.
Can anyone Help me in this Please!
Upvotes: 1
Views: 1964
Reputation: 22542
Note that, your code uses Microsoft.IdentityModel.Clients.ActiveDirectory library that is currently deprecated and no longer supported.
Alternatively, you can use Microsoft.Identity.Client package for generating access token.
In my case, I performed same steps as you in registering application and adding permissions to it:
Now, I ran below PowerShell script from same document that created certificates with .cer
and .pfx
format in specified location:
$dnsName = "mxxxxxxx.sharepoint.com"
$password = "xxxxxxx"
$folderPath = "C:\temp\certs"
$fileName = "sricert17"
$yearsValid = 10
$certStoreLocation = "cert:\LocalMachine\My"
$expirationDate = (Get-Date).AddYears($yearsValid)
$certificate = New-SelfSignedCertificate -DnsName $dnsName -CertStoreLocation $certStoreLocation -NotAfter $expirationDate -KeyExportPolicy Exportable -KeySpec Signature
$certificatePath = $certStoreLocation + '\' + $certificate.Thumbprint
$filePath = $folderPath + '\' + $fileName
$securePassword = ConvertTo-SecureString -String $password -Force -AsPlainText
Export-Certificate -Cert $certificatePath -FilePath ($filePath + '.cer')
Export-PfxCertificate -Cert $certificatePath -FilePath ($filePath + '.pfx') -Password $securePassword
Response:
I uploaded this .cer
certificate in my Azure AD application like this:
When I ran below c# code to generate access token and called SharePoint Online Rest API, I got response successfully like this:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
class Program
{
static async Task Main()
{
// Load the certificate from a file location
X509Certificate2 certificate = new X509Certificate2("C:/temp/certs/mycert17.pfx", "password");
// Create the confidential client application object
IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create("appId")
.WithCertificate(certificate)
.WithAuthority(new Uri("https://login.microsoftonline.com/tenantId"))
.Build();
// Get the access token
string[] scopes = new string[] { "https://mxxxxxxx.sharepoint.com/.default" };
AuthenticationResult authResult = await confidentialClientApplication.AcquireTokenForClient(scopes).ExecuteAsync();
// Print the access token
Console.WriteLine("Access token: {0}\n", authResult.AccessToken);
// Call SharePoint API using the access token
await CallSharePointApi(authResult.AccessToken);
}
static async Task CallSharePointApi(string accessToken)
{
try
{
Uri uri = new Uri("https://mxxxxxxxxxx.sharepoint.com"); // SharePoint URL
using (var httpClient = new HttpClient())
{
var listTitle = "srilist";
var itemID = "1"; // Replace with the actual item ID
var endpointUrl = $"{uri}/sites/sritestsite10/_api/web/lists/getbytitle('{listTitle}')/items({itemID})";
// Set the required headers
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await httpClient.GetAsync(endpointUrl);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
// Process the SharePoint API response as needed
Console.WriteLine("\nSharePoint API Response:\n" + result);
}
}
catch (HttpRequestException ex)
{
// Handle or log the exception
Console.WriteLine("Error calling SharePoint API: " + ex.Message);
}
}
}
Response:
Upvotes: 1