lateralus
lateralus

Reputation: 1030

Sharepoint Rest API Authentication issues with Access Token Header

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();
    
    
                        }
                    }
                }

Upvotes: 1

Views: 5174

Answers (1)

Jerry
Jerry

Reputation: 3625

SharePoint Online has blocked the Azure AD App Client Secret, so if you want to use Azure AD App to authentication with SharePoint Rest API, it's necessary to use Certificate option:

Calling SharePoint Online APIs using Azure AD App-Only permissions and certificate auth

Another option is to use the SharePoint hosted App Id/ Secret registered in "/_layouts/15/appregnew.aspx", this way supported the Client Secret, please check the demo test in Postman:

Accessing SharePoint Data using Postman (SharePoint REST API)

Upvotes: 2

Related Questions