I'm triggering an external web page outside of sharepoint which needs to read lists using the sharepoint web api.
HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + "/_api/web/lists");
endpointRequest.Method = "GET";
endpointRequest.Accept = "application/json;odata=verbose";
//endpointRequest.Headers.Add("Authorization", "Bearer " + accessToken);
HttpWebResponse endpointResponse = (HttpWebResponse)endpointRequest.GetResponse();
I can access the API using chrome if I'm logged in but I suspect I need the access token line.. but can't seem to find a way to populate it.
Currently it returns:
No connection could be made because the target machine actively refused it...
You need to set credential of HttpWebRequest.
Here you go:
HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + "/_api/web/lists");
string password = "XXXXX";
string userName = "XXXX";
SecureString secureString = new SecureString();
foreach (char c in password.ToCharArray())
{
secureString.AppendChar(c);
}
endpointRequest.Credentials = new SharePointOnlineCredentials(userName, secureString);
//.........
If you are using SharePoint online, it can work with my answer above because i have tested.
If you are using SharePoint 2013/2010/2016, the code will be as below.
HttpWebRequest endpointRequest = (HttpWebRequest)HttpWebRequest.Create(sharepointUrl.ToString() + "/_api/web/lists");
string password = "XXXXX";
string userName = "XXXX";
string domain = "XXX"
endpointRequest.Credentials = new NetworkCredential(userName, password, domain);
//.........
Related
I am using .net 4.8 WebClient and the Microsoft.SharePointOnline.CSOM package, trying to download files from SharePoint online.
const string username = "myusername#domain.com";
const string password = "mypassword";
const string url = "https://tenant.sharepoint.com/:b:/r/filepath.pdf";
var securedPassword = new SecureString();
foreach (var c in password.ToCharArray())
{
securedPassword.AppendChar(c);
}
var credentials = new SharePointOnlineCredentials(username, securedPassword);
using (var client = new WebClient())
{
client.Credentials = credentials;
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
client.DownloadFile(url, "C:\\temp\\test.pdf"); //this file path definitely exists
}
The error I get is a 401 unauthorized.
I logged out and logged into the SharePoint environment using the same credentials, to ensure that they are correct.
I've tried adding a couple different user agents in the header to see if that helps.
client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
//or
client.Headers.Add("User-Agent: Other");
But it didn't make any difference.
This is similar to Download File From SharePoint 365 which is using what looks like the same code as I am, but Download Document from SharePoint Online using c# webclient stopped working suggests that something has changed and this form of authentication no longer works for connecting to SharePoint online. However I have been unable to find any recent documentation on what we're supposed to use now.
You could refer to the code provided by official document.
https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-folders-and-files-with-rest
As I test,it works well.
public static void DownloadFileViaRestAPI(string webUrl, ICredentials credentials, string documentLibName, string fileName, string path)
{
webUrl = webUrl.EndsWith("/") ? webUrl.Substring(0, webUrl.Length - 1) : webUrl;
string webRelativeUrl = null;
if (webUrl.Split('/').Length > 3)
{
webRelativeUrl = "/" + webUrl.Split(new char[] { '/' }, 4)[3];
}
else
{
webRelativeUrl = "";
}
using (WebClient client = new WebClient())
{
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
client.Credentials = credentials;
Uri endpointUri = new Uri(webUrl + "/_api/web/GetFileByServerRelativeUrl('" + webRelativeUrl + "/" + documentLibName + "/" + fileName + "')/$value");
byte[] data = client.DownloadData(endpointUri);
FileStream outputStream = new FileStream(path + fileName, FileMode.OpenOrCreate | FileMode.Append, FileAccess.Write, FileShare.None);
outputStream.Write(data, 0, data.Length);
outputStream.Flush(true);
outputStream.Close();
}
}
static void Main(string[] args)
{
string siteURL = "https://contoso.sharepoint.com/sites/dev";
//set credential of SharePoint online
SecureString secureString = new SecureString();
foreach (char c in "password".ToCharArray())
{
secureString.AppendChar(c);
}
ICredentials credentials = new Microsoft.SharePoint.Client.SharePointOnlineCredentials("amos#contoso.onmicrosoft.com", secureString);
//set credential of SharePoint 2013(On-Premises)
//string userName = "Administrator";
//string password = "xxxxxxx";
//string domain = "CONTOSO";
//ICredentials credentials = new NetworkCredential(userName, password, domain);
DownloadFileViaRestAPI(siteURL, credentials, "lib", "test.css", "c:\\SPFX\\");
Console.WriteLine("success");
Console.ReadLine();
}
We use Multi-factor authentication on our Sharepoint. We are trying to download some documents from sharepoint to manipulate in our application. I have tried to access the sharepoint using both the "traditional" method as well as trying to go thru our Azure AD. Both methods dont allow us to access the sharepoint - we get permission denied
Any help would be greatly appreciated
This is what i have tried already - going thru AD
string clientId = "xxx";
string clientSecret = "yyy";
string tenant = "zzz";
AuthenticationResult result = null;
var data = AzureAdOptions.Settings.Authority;
AuthenticationContext authContext = new
AuthenticationContext(AzureAdOptions.Settings.Authority);
ClientCredential credential = new
ClientCredential(AzureAdOptions.Settings.ClientId,
AzureAdOptions.Settings.ClientSecret);
result = await
authContext.AcquireTokenAsync(AzureAdOptions.Settings.PreceptWebApiResourceId, credential);
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = await client.SendAsync(request);
and then the more "traditional way"
WebRequest request = WebRequest.Create("https://my.sharepoint.com:/sites/files/");
string userName = "mylogon";
string password = "#!";
var securePassword = new SecureString();
foreach (char c in password)
{
securePassword.AppendChar(c);
}
request.Credentials = new NetworkCredential(userName, securePassword);
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(userName + ":" + password));
request.Headers.Add("Authorization", "Basic " + encoded);
WebResponse response = request.GetResponse();
Replace the line of code below
request.Credentials = new NetworkCredential(userName, securePassword);
with
request.Credentials = new SharePointOnlineCredentials(userName, securePassword);
Or using SharePointPnPCoreOnline.
var authManager = new AuthenticationManager();
var ctx = authManager.GetWebLoginClientContext("https://contoso.sharepoint.com/");
Refer to: CSOM.MFA.cs
I'm trying to authenticate up against Sharepoint so that it's possible for me to upload files onto a specific Sharepoint site.
I'm trying to use an X.509 certificate to retrieve the access token, but I keep getting (401): Unauthorized.
Here's the way I try to retrieve the access token with the certificate:
string authority = SettingsHelper.Authority;
string clientID = SettingsHelper.ClientId;
string serverName = SettingsHelper.SharepointServerName;
//Retreive the certificate path
string certFile = Server.MapPath(SettingsHelper.CertificatePath);
string certPassword = SettingsHelper.CertificatePassword;
AuthenticationResult authenticationResult = null;
AuthenticationContext authenticationContext = new AuthenticationContext(authority);
//Create the certificate file, using the path (certFile), password (certPassword) and the MachineKeySet
X509Certificate2 cert = new X509Certificate2(certFile, certPassword, X509KeyStorageFlags.MachineKeySet);
//Create the ClientAssertionCertificate using the clientID and the actual certificate
ClientAssertionCertificate cac = new ClientAssertionCertificate(clientID, cert);
//Retreive the access token using the serverName and client assertion
authenticationResult = authenticationContext.AcquireToken(serverName, cac);
And here's how I try to upload a specific file onto a specific Sharepoint list:
WebRequest request = null;
HttpWebResponse response = null;
byte[] bytesToUpload = bytes;
var returnValue = "";
string requestUriString = string.Format("{0}/_api/web/GetFolderByServerRelativeUrl(#sru)/Files/Add(url=#fn,overwrite=true)?#sru='{1}'&#fn='{2}'", url, HttpUtility.UrlEncode(serverRelativeUrl), HttpUtility.UrlEncode(fileName));
request = (HttpWebRequest)HttpWebRequest.Create(requestUriString);
request.Method = "POST";
(request as HttpWebRequest).Accept = "*/*";
request.ContentType = "application/json;odata=verbose";
request.Headers.Add("Authorization", String.Format("Bearer {0}", authenticationResult.AccessToken));
request.ContentLength = bytesToUpload.Length;
// Write the local file to the remote system
using (Stream requestStream = request.GetRequestStream())
{
BinaryWriter writer = new BinaryWriter(requestStream);
writer.Write(bytesToUpload, 0, bytesToUpload.Length);
writer.Close();
}
// Get a web response back
response = (HttpWebResponse)request.GetResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default))
{
returnValue = sr.ReadToEnd();
sr.Close();
}
if (request.RequestUri.ToString().Contains("GetFolderByServerRelativeUrl") == true)
{
returnValue = "";
}
Some of the variables comes from the parameters:
UploadEmail(System.IO.File.ReadAllBytes(emlFilePath), "https://(blablabla).sharepoint.com", "sites/(bla)/(bla)/Emails", email.Subject + ".msg");
I'm not sure what's wrong, and I'm definitely not sure how to fix this.
NOTE: Please don't tell me to use NetworkCredentials, I'd rather use the certificate or something else, but not NetworkCredentials
EDIT
Managed to debug the code and find this in the response header of the WebRequest:
The better approach would be using the SharePoint Client Side Object Model (as hbulens suggested in comments).
Here's the code that uploads the file to the library in O365 (just replace the string literals with your own details):
string username = "YOUR_USERNAME";
string password = "YOUR_PASSWORD";
string siteUrl = "https://XXX.sharepoint.com";
ClientContext context = new ClientContext(siteUrl);
SecureString pass = new SecureString();
foreach (char c in password.ToCharArray()) pass.AppendChar(c);
context.Credentials = new SharePointOnlineCredentials(username, pass);
Site site = context.Site;
context.Load(site);
context.ExecuteQuery();
Web web = site.OpenWeb("YOUR_SUBSITE");
context.Load(web);
context.ExecuteQuery();
List docLib = web.Lists.GetByTitle("YOUR_LIBRARY");
context.Load(docLib);
FileCreationInformation newFile = new FileCreationInformation();
string filePath = #"YOUR_LOCAL_FILE";
newFile.Content = System.IO.File.ReadAllBytes(filePath);
newFile.Url = System.IO.Path.GetFileName(filePath);
Microsoft.SharePoint.Client.File uploadFile = docLib.RootFolder.Files.Add(newFile);
context.Load(uploadFile);
context.ExecuteQuery();
You can run it in console application. Two dll's that you need to reference are:
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime.dll
Here is the sample code for PHP Webservice client that works:
$options = array();
$options['trace'] = 1;
$options['login'] = 'username';
$options['password'] = 'password';
$client = new SoapClient("http://wsurl.com/pt/wsdl", $options);
I would like to access this webservice using c# but having a hard time doing the authentication. Do I need to explicitly set the soap headers or there is a built in way to send credentials in .NET
There are two ways to do this because servers handle authentication differently. First you could use something like this:
var req = WebRequest.Create(<your url>);
NetworkCredential creds = new NetworkCredential(<username>, <password>);
req.Credentials = creds;
var rep = req.GetResponse();
However if you need an actual Authroization header you will want to use this code
public void SetBasicAuthHeader(WebRequest req, String userName, String userPassword)
{
string authInfo = userName + ":" + userPassword;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
req.Headers["Authorization"] = "Basic " + authInfo;
}
And then your request code becomes
var req = WebRequest.Create(<your url>);
SetBasicAuthHeader(req, username, password);
rep = req.GetResponse();
Let me know if you have any questions.
If you add a service reference in your C# project, you can just call your service like this:
var proxy = new YourServiceClient();
proxy.ClientCredentials.UserName.UserName = "username";
proxy.ClientCredentials.UserName.Password = "password";
More information can be found here: http://msdn.microsoft.com/en-us/library/ms733775.aspx.
I'm trying to read files from a SharePoint document library using HttpWebRequest. In order to do that I have to pass some credentials. I'm using the below request:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/msexcel";
request.UserAgent = "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0";
request.Credentials = new NetworkCredential(UserName, PassWord);
Is this the correct way to pass credentials?
You could also use:
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
If you need to run request as the current user from desktop application use CredentialCache.DefaultCredentials (see on MSDN).
Your code looks fine if you need to run a request from server side code or under a different user.
Please note that you should be careful when storing passwords - consider using the SecureString version of the constructor.
If you need to set the credentials on the fly, have a look at this source:
http://spc3.codeplex.com/SourceControl/changeset/view/57957#1015709
private ICredentials BuildCredentials(string siteurl, string username, string password, string authtype) {
NetworkCredential cred;
if (username.Contains(#"\")) {
string domain = username.Substring(0, username.IndexOf(#"\"));
username = username.Substring(username.IndexOf(#"\") + 1);
cred = new System.Net.NetworkCredential(username, password, domain);
} else {
cred = new System.Net.NetworkCredential(username, password);
}
CredentialCache cache = new CredentialCache();
if (authtype.Contains(":")) {
authtype = authtype.Substring(authtype.IndexOf(":") + 1); //remove the TMG: prefix
}
cache.Add(new Uri(siteurl), authtype, cred);
return cache;
}