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);
Related
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();
}
I am trying to access google sites feed by using google service account. But I get "The remote server returned an error: (403) Forbidden."(Not authorized to access this feed) error.
The code written is as follows:
var certificate = new X509Certificate2(filePath, password, X509KeyStorageFlags.Exportable);
var serviceAccountCredentialInitializer =new ServiceAccountCredential.Initializer("abc#developer.gserviceaccount.com")
{Scopes = new[] {"https://sites.google.com/feeds/"}}.FromCertificate(certificate);
var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
if(!credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Result)
throw new InvalidOperationException("Access token request failed.");
var requestFactory = new GDataRequestFactory(null);
requestFactory.CustomHeaders.Add("Authorization: Bearer " + credential.Token.AccessToken);
//SitesService class inherits MediaService
SitesService service = new SitesService(null)
{
RequestFactory = requestFactory
};
Stream feed = service.Query(new Uri("https://sites.google.com/feeds/content/domain-name/site-name?path=page-path"));
I have also granted access to required scopes to google service account from admin panel. But still same error.
Can someone please tell me, what is wrong in my code?
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 have a client who is implementing customer portals in Sharepoint 2013 Online. The current program distributes documents to the customers by mail. Now we have to upload the documents to the customer portal.
I try to use the copy webservice in sharepoint. I created a test project and added the webservice as Web Reference and wrote the following testcode:
static void Main(string[] args)
{
string baseUrl = "https://mycustomer.sharepoint.com/sites/";
string customer = "customerportalname";
string serviceUrl = "/_vti_bin/copy.asmx";
string destinationDirectory = "/folder/";
string fileName = "uploaded.xml";
string username = "username#outlook.com";
string password = "password";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml("<fiets><onderdeel>voorwiel</onderdeel><onderdeel>achterwiel</onderdeel><onderdeel>trappers</onderdeel><onderdeel>stuur</onderdeel><onderdeel>frame</onderdeel></fiets>");
byte[] xmlByteArray;
using (MemoryStream memoryStream = new MemoryStream())
{
xmlDocument.Save(memoryStream);
xmlByteArray = memoryStream.ToArray();
}
string destinationUrl = string.Format("{0}{1}{2}{3}", baseUrl, customer, destinationDirectory, fileName);
string[] destinationUrlArray = new string[] { destinationUrl };
FieldInformation fieldInfo = new FieldInformation();
FieldInformation[] fields = { fieldInfo };
CopyResult[] resultsArray;
using (Copy copyService = new Copy())
{
copyService.PreAuthenticate = true;
copyService.Credentials = new NetworkCredential(username, password);
copyService.Url = string.Format("{0}{1}", baseUrl, serviceUrl);
copyService.Timeout = 600000;
uint documentId = copyService.CopyIntoItems(destinationUrl , destinationUrlArray, fields, xmlByteArray, out resultsArray);
}
}
When I execute the code I recieve the following error:
The request failed with the error message:
--
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
--
It looks like I'm not authenticated and get redirected. The credentials however are correct.
Does anyone have an idea? Thanks in advance!
UPDATE
To be able to connect to SharePoint 2013 Online you have to attach the Office 365 authentication cookies as explained in this post.
My problem however is that there is also an ADFS involved. How can I autheticate against the ADFS?
This error most probably occurs due to incorrect authentication mode.
Since SharePoint Online (SPO) uses claims-based authentication, NetworkCredential Class can not be utilized for authentication in SPO.
In order to perform the authentication against the ADFS in SPO you could utilize SharePointOnlineCredentials class from SharePoint Online Client Components SDK.
How to authenticate SharePoint Web Services in SharePoint Online (SPO)
The following example demonstrates how to retrieve authentication cookies:
private static CookieContainer GetAuthCookies(Uri webUri, string userName, string password)
{
var securePassword = new SecureString();
foreach (var c in password) { securePassword.AppendChar(c); }
var credentials = new SharePointOnlineCredentials(userName, securePassword);
var authCookie = credentials.GetAuthenticationCookie(webUri);
var cookieContainer = new CookieContainer();
cookieContainer.SetCookies(webUri, authCookie);
return cookieContainer;
}
Example
string sourceUrl = "https://contoso.sharepoint.com/Documents/SharePoint User Guide.docx";
string destinationUrl = "https://contoso.sharepoint.com/Documents/SharePoint User Guide 2013.docx";
FieldInformation[] fieldInfos;
CopyResult[] result;
byte[] fileContent;
using(var proxyCopy = new Copy())
{
proxyCopy.Url = webUri + "/_vti_bin/Copy.asmx";
proxyCopy.CookieContainer = GetAuthCookies(webUri, userName, password);
proxyCopy.GetItem(sourceUrl,out fieldInfos,out fileContent);
proxyCopy.CopyIntoItems(sourceUrl,new []{ destinationUrl}, fieldInfos, fileContent, out result);
}
References
Remote Authentication in SharePoint Online Using Claims-Based
Authentication
SharePoint Online Client Components SDK
In my case (on premise) i have that error. when i changed at iis SharePoint authentication for web application , and disable "Forms Authentication". Now, i canĀ“t enter to SharePoint by UI, but the Web Service works... So I have revert and I have been looking and...
[Paul stork] The Web Application for this site is running in Classic Mode rather than Claims mode. This can happen if you create the web app using Powershell or upgrade from 2010. You can use PowerShell to change it.
http://technet.microsoft.com/en-us/library/gg251985.aspx
I have tried the Web Service in another new application created by UI in Central Administration (in same farm) and it had worked. The problem was the web application.
To try:
http://sharepointyankee.com/2011/01/04/the-request-failed-with-the-error-message-object-moved-sharepoint-2010-web-services-fba/
Extend your mixed authentication web application, and create a zone just for Windows Authentication, then change the Web Reference URL in the properties of your web service, to use that extended URL and port. You should have no issues of this kind anymore.
I want to use the google analytics api in my MVC website, im authenticating using the api service account and oauth2 with have no issues on my localhost but as soon as I deploy to Azure i get a 502 error:
"502 - Web server received an invalid response while acting as a
gateway or proxy server. There is a problem with the page you are
looking for, and it cannot be displayed. When the Web server (while
acting as a gateway or proxy) contacted the upstream content server,
it received an invalid response from the content server."
heres my code:
const string ServiceAccountUser = "xxxxxxxxxx-cpla4j8focrebami0l87mbcto09j9j6k#developer.gserviceaccount.com";
AssertionFlowClient client = new AssertionFlowClient(
GoogleAuthenticationServer.Description,
new X509Certificate2(System.Web.Hosting.HostingEnvironment.MapPath("/Areas/Admin/xxxxxxxxxxxxxxxxxx-privatekey.p12"),
"notasecret", X509KeyStorageFlags.Exportable))
{
Scope = AnalyticsService.Scopes.AnalyticsReadonly.GetStringValue(),
ServiceAccountId = ServiceAccountUser //Bug, why does ServiceAccountUser have to be assigned to ServiceAccountId
//,ServiceAccountUser = ServiceAccountUser
};
OAuth2Authenticator<AssertionFlowClient> authenticator = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
I cant figure out whats causing it? Am im missing something within Azure?
Thanks for any help.
I also ran into the same issue but passing X509KeyStorageFlags.MachineKeySet into the constructor as well fixed the issue for me.
X509Certificate2 certificate = new X509Certificate2(file, "key", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
After hours of pain on this exact same problem, I found a work around by piecing together various sources of info.
The problem arises from trying to read the p12 file from the Azure web site, i.e. this line in my code fails
var key = new X509Certificate2(keyFile, keyPassword, X509KeyStorageFlags.Exportable);
No idea why, but it works if you split the file into a cer and key.xml file?
Firstly, extract these files, (I just used a console app)
// load pfx/p12 as "exportable"
var p12Cert = new X509Certificate2(#"c:\Temp\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-privatekey.p12", "notasecret", X509KeyStorageFlags.Exportable);
// export .cer from .pfx/.p12
File.WriteAllBytes(#"C:\Temp\MyCert.cer", p12Cert.Export(X509ContentType.Cert));
// export private key XML
string privateKeyXml = p12Cert.PrivateKey.ToXmlString(true);
File.WriteAllText(#"C:\Temp\PrivateKey.xml", privateKeyXml);
Then copy them to your website then load them in like so
//Store the authentication description
AuthorizationServerDescription desc = GoogleAuthenticationServer.Description;
//Create a certificate object to use when authenticating
var rsaCryptoServiceProvider = new RSACryptoServiceProvider();
rsaCryptoServiceProvider.FromXmlString(File.ReadAllText(keyFile));
var key = new X509Certificate2(certFile) {PrivateKey = rsaCryptoServiceProvider};
//Now, we will log in and authenticate, passing in the description
//and key from above, then setting the accountId and scope
var client = new AssertionFlowClient(desc, key)
{
//cliendId is your SERVICE ACCOUNT Email Address from Google APIs Console
//looks something like 12345-randomstring#developer.gserviceaccount.com
//~IMPORTANT~: this email address has to be added to your Google Analytics profile
// and given Read & Analyze permissions
ServiceAccountId = clientId,
Scope = "https://www.googleapis.com/auth/analytics.readonly"
};
//Finally, complete the authentication process
//NOTE: This is the first change from the update above
var auth = new OAuth2Authenticator<AssertionFlowClient>(client, AssertionFlowClient.GetState);
//First, create a new service object
//NOTE: this is the second change from the update
//above. Thanks to James for pointing this out
var gas = new AnalyticsService(new BaseClientService.Initializer { Authenticator = auth });
This now works for me and I hope it helps you.