I am trying to connect to a Sharepoint site which I can open & navigate in a browser, so I do have permissions. But in my .NET Framework 4.7.2 Console app, I am getting "401 unauthorized". What am I missing? I am using the "Microsoft.SharePoint.Client.Online.CSOM" nuget package, not sure if that's the right one, but only there I had the "SharePointOnlineCredentials" which other posts recommend to use.
var siteUrl = "https://mycompany.sharepoint.com";
var context = new ClientContext(siteUrl);
var securePassword = new NetworkCredential("", "mypw").SecurePassword;
context.Credentials = new SharePointOnlineCredentials("myusername#mydomain", securePassword);
var web = context.Web;
context.Load(web);
context.ExecuteQuery(); // 401 UNAUTHORIZED
When I am using the "Microsoft.SharePointOnline.CSOM" package instead, I am getting this error:
"Cannot contact web site 'https://mycompany.sharepoint.com/' or the web site does not support SharePoint Online credentials. The response status code is 'Unauthorized'. The response headers are 'X-SharePointHealthScore=0, X-MSDAVEXT_Error=917656; Access+denied.+Before+opening+files+in+this+location%2c+you+must+first+browse+to+the+web+site+and+select+the+option+to+login+automatically"
Until now, I couldn't find anything that helped.
Do I need to register the app in Azure AD or is that only needed for .NET Standard?
It's now working with the "PnP.Framework" nuget package and this code:
var credentials = new System.Net.NetworkCredential("myusername#mydomain", "mypw");
var authManager = new AuthenticationManager(credentials.UserName, credentials.SecurePassword);
using (var context = authManager.GetContext("https://mycompany.sharepoint.com"))
{
var web = context.Web;
context.Load(web, w => w.Id, w => w.Title, w => w.Url);
context.ExecuteQuery();
}
Related
"Operation has timed out" error while connecting to Office 365 Sharepoint from asp.net web application
I have tried finding answers and implementing solutions like below:
How to connect to SharePoint on Office 365 with CSOM from C#?
Also some blogs suggested making an asynchronous query, which does not throw error but also does not give any results.
Also tried setting timeout property without any help.
Below is my code:
SharePointOnlineCredentials networkCredential = new
SharePointOnlineCredentials(SharePointUser, SharePointPassword);
Context = new ClientContext(SharePointURL);
Context.Credentials = networkCredential;
Web = Context.Web;
Context.Load(Web);
Context.ExecuteQuery();`
Also, strangely I am able to connect and get data using Console application, but I need to get this working in web application.
After a lot of search I realized that we need proxy to connect to Sharepoint Online and implemented following code to achieve
clientContext.ExecutingWebRequest += (s, e) =>
{
e.WebRequestExecutor.WebRequest.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
};
Add clientContext.RequestTimeout = -1 in the code, the code below for your reference.
string siteUrl = "https://tenant.sharepoint.com/sites/lz";
string userName = "lz#tenant.onmicrosoft.com";
string password = "xxx";
var securePassword = new SecureString();
foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);
using (ClientContext clientContext = new ClientContext(siteUrl))
{
clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);
clientContext.RequestTimeout = -1;
var web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();
}
I am having problems accessing SharePoint using both CSOM and the REST service from a .NET Core console application.
First I created a console application that targets .NET Framework 4.6.1, installed the Microsoft.SharePointOnline.CSOM nuget package, and added two sample methods to connect to SharePoint using hard-coded user credentials. This works.
public static void CsomCall()
{
var password = "password";
var securePassword = new SecureString();
foreach (var c in password.ToCharArray()) securePassword.AppendChar(c);
using (ClientContext context = new ClientContext("https://siteurl"))
{
context.Credentials = new SharePointOnlineCredentials("user#domain", securePassword);
Web web = context.Web;
context.Load(web);
context.ExecuteQuery();
Console.WriteLine(web.Title);
}
}
private static void RestCall()
{
var password = "password";
var securePassword = new SecureString();
foreach (var c in password.ToCharArray()) securePassword.AppendChar(c);
var credentials = new SharePointOnlineCredentials("user#domain", securePassword);
using (WebClient client = new WebClient())
{
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
client.Credentials = credentials;
client.Headers.Add(HttpRequestHeader.ContentType, "application/json;odata=verbose");
client.Headers.Add(HttpRequestHeader.Accept, "application/json;odata=verbose");
var content = client.DownloadString("https://siteurl/_api/web/lists");
Console.WriteLine(content);
}
}
Then I created a .NET Core console application and copied across the methods above. I understand that SharePoint CSOM is not yet supported in .NET Core, so I used the workaround suggested here and manually referenced Microsoft.SharePoint.Client.Portable.dll, Microsoft.SharePoint.Client.Runtime.Portable.dll and Microsoft.SharePoint.Client.Runtime.Windows.dll.
I had to make a couple of changes to compile the code:
.ExecuteQueryAsync() instead of .ExecuteQuery()
var credentials = new SharePointOnlineCredentials("user#domain", password); Note, password is a plain string in Microsoft.SharePoint.Client.Runtime.Portable.
When running CsomCall it fails when accessing web.Title:
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException: 'The property or field 'Title' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.'
When running RestCall it fails with an error on client.DownloadString:
System.Net.WebException: 'The remote server returned an error: (401) Unauthorized.'
Is it possible to set up SharePointOnlineCredentials to work with .NET Core? Searches on stack overflow indicate this should be possible, but I just can't seem to make it work.
Ultimately we would like to build a Web API service using ASP.NET Core to generate documents for internal users (reading document templates from SharePoint, generating a new document and saving back to SharePoint). Using either CSOM or REST, and running on Windows OS for now.
The REST call is wrong. You have to get a token using the credentials. Also, the WebClient is mostly deprecated, use the HttpClient class instead.
Look at this example:
public const string BaseUri = "https://example.sharepoint.com";
private static HttpClient _client;
public static void Initialize()
{
SharePointOnlineCredentials currentCredentials = GetCredentialsHere();
var handler = new HttpClientHandler
{
Credentials = currentCredentials
};
_client = new HttpClient(handler);
// you are missing this line
handler.CookieContainer.SetCookies(BaseUri, currentCredentials.GetAuthenticationCookie(BaseUri));
_client.BaseAddress = BaseUri;
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.MaxResponseContentBufferSize = 2147483647;
}
I am programming an VSTO Word Addin. This addin read information (list) from sharepoint online.
How can I get Credentials from ActiveDocument class to create a ContextClient
?
I tried to use System.Net.CredentialCache.DefaultCredentials
ClientContext context = new ClientContext(url);
context.AuthenticationMode = ClientAuthenticationMode.Default;
context.Credentials = System.Net.CredentialCache.DefaultCredentials;
Web web = context.Web;
context.Load(web);
context.Load(web.CurrentUser);
context.ExecuteQuery();
Web rootWeb = context.Site.RootWeb;
context.Load(rootWeb, rw => rw.Url);
context.ExecuteQuery();
rootContextUrl = context.Site.RootWeb.Url;
How can I make it run with Sharepoint on line. It works in Sharepoint on premise.
Thanks
Problem
I have been trying to figure out how to find a SharePoint path for a user when using OAuth2 Client Credential Flow (where an application has permission to read all users' SharePoint files using an Office 365 administrator's one-time acceptance)
I have my client application setup in Azure and am able to read files if I hard-code the SharePoint URL - so I know it is setup correctly.
But I need to "discover" the SharePoint URL so it will be change-tolerant and reusable across customers.
Related Articles:
Different OAuth2 Flows
Using OAuth2 Flow for Exchange
Code
var azureAdAuthority = "https://login.windows.net/{tenant-id}/oauth2/authorize".Replace("{tenant-id}", tenantId);
var discoveryUri = "https://api.office.com/discovery/v1.0/me/";
var discoveryResourceUri = "https://api.office.com/discovery/";
// discover contact endpoint
var cert = new X509Certificate2(certFilePath, certFilePassword, X509KeyStorageFlags.MachineKeySet);
var clientAssertion = new ClientAssertionCertificate(clientId, cert);
var userIdentifier = new UserIdentifier(userObjectId, UserIdentifierType.UniqueId);
var userAssertion = new UserAssertion(userObjectId);
// create auth context
var authContext = new AuthenticationContext(azureAdAuthority, false);
// create O365 discovery client
var discovery = new DiscoveryClient(new Uri(discoveryUri),
() => authContext.AcquireTokenSilent(discoveryResourceUri, clientAssertion, userIdentifier).AccessToken);
// query discovery service for endpoint for 'calendar' endpoint
var dcr = await discovery.DiscoverCapabilityAsync("MyFiles");
This and many other variations throw exceptions from the AcquireTokenSilent function.
If I don't use a "userIdentifier" and call the AcquireToken function it succeeds, but the DiscoverCapabilityAsync function fails.
I was working with .NET Google Document List API and found stuck myself somewhere.
I want to upload a document using 2 Legged OAuthentication as I have register my application in Google Marketplace, then install it to my domain.
Now I am using 2 legged OAuthentication to interact with data stored in google and working fine.
RequestSettings settings = new RequestSettings(APPLICATION_NAME, CONSUMER_KEY, CONSUMER_SECRET, currentUser, DOMAIN);
Below is my code which is not working and gives 401 unauthorized error:
GOAuthRequestFactory requestFactory = new GOAuthRequestFactory("cl", APPLICATION_NAME);
requestFactory.ConsumerKey = CONSUMER_KEY;
requestFactory.ConsumerSecret = CONSUMER_SECRET;
DocumentsService service = new DocumentsService(APPLICATION_NAME);
service.RequestFactory = requestFactory;
service.UploadFile(fileNameWithPath, fileName, contentType, false);