Sharepoint Rest API Authentication issues with Access Token Header

sp13test 281 Reputation points
2021-04-19T08:33:24.317+00:00

I'm trying to implement a C# program to connect to Sharepoint API through modern authentication (Client ID\ Client Secret).

I've registered an APP with Sharepoint overall permissions on Azure Active Directory, in order to generate Client Id and Client Secret.

Next steps should be retrieval of the Access Token from the Microsoft login page, and then construction of all following requests using the bearing token I've generated.

Retrieval of the Access Token just works fine. The problem is when I try to include the token in the authorization header on the following calls.

I always get 401 Unhautorized when building my requests from code. Debugging the response content, what I get is "x-ms-diagnostics: 3000006;reason="Token contains invalid signature"; category"invalid_client". Instead if I try to replicate the call in Postman I get the following error "{"error_description":"Unsupported security token."}".

I provide my code below. Does anybody knows what is going on?

     var b2cAuthUri = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";

                var client = new HttpClient();

                var dict = new Dictionary<string, string>();
                dict.Add("Content-Type", "application/x-www-form-urlencoded");
                dict.Add("grant_type", "client_credentials");
                dict.Add("client_id", clientId);
                dict.Add("client_secret", clientSecret);
                dict.Add("scope", scope);

                // Execute post method
                using (var methodResp = client.PostAsync(b2cAuthUri, new FormUrlEncodedContent(dict)))
                {

                    var callResult = methodResp.Result.Content.ReadAsStringAsync().Result;
                    if (!string.IsNullOrEmpty(callResult))
                    {
                        //I have my Access Token here :)
                        using (MemoryStream DeSerializememoryStream = new MemoryStream())
                        {


                            //initialize DataContractJsonSerializer object and pass custom token class type to it
                            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AccessToken));

                            //user stream writer to write JSON string data to memory stream
                            StreamWriter writer = new StreamWriter(DeSerializememoryStream);
                            writer.Write(callResult);
                            writer.Flush();

                            DeSerializememoryStream.Position = 0;
                            //get the Desrialized data in object of type Student
                            AccessToken SerializedObject = (AccessToken)serializer.ReadObject(DeSerializememoryStream);
                            var tokenBytes = System.Text.Encoding.UTF8.GetBytes(SerializedObject.access_token);
                            //64bit serialized token
                            var tokenBase64 = System.Convert.ToBase64String(tokenBytes);

                            //Here I try to make a call with the access token as header
                            var testURI = "https://myorg.sharepoint.com/sites/crmkb/_api/web/lists";

                            HttpWebRequest testReq = (HttpWebRequest)HttpWebRequest.Create(testURI);
                            testReq.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + tokenBase64);
                            testReq.Method = "GET";
                            //This fails on 401 code
                            HttpWebResponse response = (HttpWebResponse)testReq.GetResponse();


                        }
                    }
                }
Microsoft 365 and Office SharePoint Server Development
0 comments No comments
{count} votes

Accepted answer
  1. MichaelHan-MSFT 18,126 Reputation points
    2021-04-20T02:54:51.937+00:00

    Hi @sp13test ,

    The way you used to get access token is for Graph API authentication, it would not work for SharePoint authentication.

    In Postman, you could get the access token like this:

    Grant Type :         Authorization Code   
    Callback Url :       this should be the AAD App redirect Url   
    Auth URL :           https://login.microsoftonline.com/common/oauth2/authorize?resource=https%3A%2F%2F<tenant_name>.sharepoint.com    
    Access Token URL :   https://login.microsoftonline.com/common/oauth2/token    
    Client ID :          <client_ID>    
    Client Secret :      <Client-secret>    
    

    88489-image.png

    When you click Get Access Token, it would request you to sign in. After signing in, you would access it successfully.

    Besides, you could use certification option for authentication: https://learn.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread

    Reference: https://www.ludovicmedard.com/use-postman-and-azure-ad-to-send-rest-request-to-sharepoint-online/

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.