I've tried to use Microsoft Graph to pull some files from a shared link. However, when I try to do that using the Microsoft Graph Explorer, it returns:
"error": {
"code": "invalidRequest",
"message": "The site in the encoded share URI is invalid.",
"innerError": {
"request-id": "e07b0df4-88e0-49fd-97e4-eccaaf887d6e",
"date": "2019-11-29T19:05:52"
}
}
The encoding code is this(same as on the docs):
string base64Value =
Convert
.ToBase64String(UTF8
.GetBytes("https://1drv.ms/f/s!An8UzxYP03zbg5lyUW0nVFclockIaw"));
string encodedUrl = "u!" +
base64Value.TrimEnd('=')
.Replace('/', '_')
.Replace('+', '-');
The link is in the code and goes to an empty shared folder (for testing purposes).
i had the same problem, turned out i wasn't logged into graph under my account
derp.
UPDATE
Soo, a couple of months have passed and I have managed to fix my problem:
How did I do it?
TLDR: The share URI isn't extracted as MS tells you (for whatever reason)
Let's take my example folder:
https://1drv.ms/f/s!An8UzxYP03zbg5lyUW0nVFclockIaw
In this case, the URI is everything after(including)the "s" part, so in my case it's s!An8UzxYP03zbg5lyUW0nVFclockIaw
CODE
private static string GetIDFromLink(string website)
{
return "s!" + website.TrimStart("https://1drv.ms/f/".ToCharArray());
}
Don't forget that you MUST be logged in to MSGraph and have the proper permission to access files
Also, if you're using the "Application Daemon" method(aka, no user sign-in) you must have a SharePoint 365 subscription active(at least from what I've observed, I would like to be wrong on that)
Related
We are implementing a file store in our application and we store all the files in private containers in Azure Blob Storage. We have a virtual folder system which we replicate in our Blob storage.
For example, Let's say i work for Company A, and i upload file_1.txt to Folder #1, it will reside in /vault/Company A/Folder #1/file_1.txt in the Blob storage.
We generate SAS tokens using the following code:
public static Uri GetServiceSasUriForCloudBlockBlob(CloudBlockBlob cloudBlockBlob, string permissions = "r")
{
var sasBuilder = new SharedAccessBlobPolicy()
{
SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5),
SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddMinutes(5),
Permissions = SharedAccessBlobPolicy.PermissionsFromString(permissions)
};
var sasUri = cloudBlockBlob.GetSharedAccessSignature(sasBuilder);
return new Uri(cloudBlockBlob.Uri + sasUri);
}
However, this does not work. The error we get is:
<Error>
<script type="text/javascript"/>
<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:f82118d1-101e-002a-1381-97ac16000000 Time:2022-07-14T12:55:34.6370028Z</Message>
<AuthenticationErrorDetail>Signature did not match. String to sign used was r 2022-07-14T12:50:27Z 2022-07-14T13:00:27Z /blob/[blobname]/vault/Company A/Folder #1/file_1.txt 2019-07-07 b </AuthenticationErrorDetail>
</Error>
When generating a SAS token from the Azure Portal or the Azure Storage Explorer there is no problem
It seems to be an issue with the special characters in the path to the file in the Blob. So we tried escaping all spaces and special characters manually to fix this issue, however when doing this the CloudBlockBlob encodes it again (e.g.: it escapes My%20File.txt to My%2520File.txt).
Currently the only operation we use is Read on Objects, but this may be expanded in the future.
We could disallow spaces and special character in folders/files but this doesn't feel like solving the issue but working around it. How can we fix this without implementing naming policies?
EDIT: Turns out this was a design issue, and while the SDK docs never explicitly disencourages the use unescaped blob paths it does disallow container names with anything other than alphanumerics and dashes.
For anyone having the same issue (whether on SDK version 11 or 12), i can highly recommend not using spaces/special characters without encoding them part by part,
var fileName = "file.txt"
// Note that the order here matters
var folderNames = ["Folder #1", "Folder #1.1"]
// becomes: Folder+%25231/Folder+%25231.1
var encodedPath = folderNames.Select(WebUtility.UrlEncode).Aggregate((x, y) => x + "/" + y);
// becomes: Folder+%25231/Folder+%25231.1/file.txt
var blobPath = ${encodedPath}/{fileName}"
This looks worse in Azure Storage Explorer but this does circumvent issues with encoding string programmatically
I'm trying to write a method that gets the parent folder of the folder whose Id is passed in. I have tried many different variations, most of which come from accepted answers here, but every one causes an exception.
For example, the following code...
public async Task<DriveFile> GetParentFolder(string folderId) {
FilesResource.ListRequest request = _service.Files.List();
request.Q = $"parents contains '{folderId}'";
request.Fields = "*";
FileList files = await request.ExecuteAsync();
return files.Files[0];
}
...throws the following exception...
Error: The service drive has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Invalid Value [400]
Errors [
Message[Invalid Value] Location[q - parameter] Reason[invalid] Domain[global]
]
I have tried many values for the Q and Fields properties, but all result in the same exception.
I have other code working with the API, so it's not the basic service that's a problem, and I've used the API to get the Ids of some folders, so I know I'm passing in a valid value.
One of the problems is that v2 of the API had a Parents list, which looks like it does what I want, but this seems to be missing in v3.
Anyone able to help me? Thanks
Your going about it the wrong way you dont need to use file.list you already have the file id just use file.get.
Lets say i have the folder id here.
{
"kind": "drive#file",
"id": "1bzDkXlcND_yycIcbqwr1YYZ98-Yv7SG7",
"name": "Current Badges (2019-21)",
"mimeType": "application/vnd.google-apps.folder"
},
As you can see in this example i have the id and the mime type is a folder.
All i need to do is do a file.get
var request = _service.Files.Get("1bzDkXlcND_yycIcbqwr1YYZ98-Yv7SG7");
request.Fields = "parents";
var response = request.Execute();
The response will contain a filed called parents which is the parent of the folder.
As you can see if you already know the file id or in this case the folder id. Then you really just need to use file.get to get all the information about that id.
There's really no reason to use file.list.
I used "NReco.PdfGenerator.dll" to my web project (Visual studio 2012, c#),
and it can export from internet url (like http://google.com.tw) succsssfully
But when I change the url to internal url (out company internal system)
and I got this error message:
"Cannot generate PDF: Exit with code 1 due to network error: AuthenticationRequiredError(exit code: 1)"
Here is my code:
new NReco.PdfGenerator.HtmlToPdfConverter().GeneratePdfFromFile("http://xxx.xxx.xxxx", null, AppDomain.CurrentDomain.BaseDirectory + "test.pdf");
Could anyone help this problem ???
Thank you so much
AuthenticationRequiredError is returned by wkhtmltopdf (internally PdfGenerator executes it in the separate process) when specified URL returns HTTP code 401 (Unauthorized).
In most cases this mean that this web page can be accessed only by authenticated users; in most web applications authentication token is passed with cookie or HTTP header.
You can pass either cookie with special wkhtmltopdf options, for example:
var htmlToPdf = new NReco.PdfGenerator.HtmlToPdfConverter();
htmlToPdf.CustomWkHtmlArgs = " --cookie <name> <value>";
option for extra HTTP header:
htmlToPdf.CustomWkHtmlArgs = " --custom-header <name> <value> ";
Note that it is not possible to render URLs that require windows authentication; in this case alternative auth mechanism should be used for accessing these pages by wkhmtltopdf.
I'm using Facebook SDK ( http://facebooksdk.net ) and want to get friend list with the following information:
1. ID
2. Name
3. Photo
4. link
5. Email
6. etc...
I have read Facebook's documentation and different posts of forum (including stackoverflow), but I'm confused. After it I'm not sure, is it possible to get this information by API request or not. First at all, this request returns only ID and name data:
var client = new FacebookClient("XXX");
dynamic friends = client.Get("/me/friends");
Next step - try to modify this request to specify returned fields:
var client = new FacebookClient("XXX");
dynamic friends = client.Get("/me/friends?fields=about,bio,age_range,first_name,gender,address,email,location,link,languages,username,last_name,timezone,updated_time");
it returns only some fields:
"first_name": "XXX",
"gender": "male",
"link": "https://www.facebook.com/XXX",
"username": "XXX",
"last_name": "XXX",
"updated_time": "2013-09-07T12:18:34+0000",
"id": "XXX"
is it possible to return more fields? As I understood, it depends on permissions. I try to set these permissions. I go to Applications -> MyApp -> Permissions, and see, that field "User & Friend Permissions" is empty. I try to set some permissions, i.e.
user_about_me,friends_about_me
and after click "Save" button I see the message:
Changes saved. Note that your changes may take several minutes to
propagate to all servers.
but field "User & Friend Permissions" is empty again. First question : why and how can I see all set permissions?
secondly - I don't see any changes in my request via FacebookClient (but field "About" is added to request). Why?
Thanks
The fields that you can get without any extra permissions:
first_name
gender
link
username
last_name
updated_time
id
With permissions-
friends_about_me - about, bio
friends_location - location
friends_likes - languages
Invalid fields (I don't know from where you saw these)-
age_range
address
email
timezone
Another thing that you are not getting all the fields is because the permissions are not being asked by the user (and hence not granted any to your app).
This is because, you have to add the permissions in your code, while login-in the user- not just adding permissions in the App Settings.
For eg, if you are using javascript sdk, it is done using the scope parameter. Reference
You can always test your call here: Graph API Explorer
To answer your first question, you can see the answer here, use the Facebook graph api and search /{user id}/permissions.
Some clerification for the rest. You can't get friends email address as answered here. In order to get the friends profile picture you need to add the field picture (you can specify the size like this picture.width().height().
I reccomend you try to use Facebooks Graph Api Explorer to play with the permissions and the info you request.
I'm using Twitterizer library for posting tweets within a web-site into my twitter account. It works just fine on site, running on my local server (authenticates with OAuth through twitter app and posts a tweet).
But when I'm trying to post a tweet on production server, Twitterizer says: "Result = Unauthorized. ErrorMessage = Could not authenticate with OAuth."
I double checked consumer keys, also tried to reset the keys and try again - same result.
Twitter application has read/write access to my twitter account and is not blocked.
This problem appeared suddenly after a period of successful working for about a month, when tweets were posted every hour or so.
What is the problem here?
UPDATE
It seems, that other guys also face this problem: https://dev.twitter.com/discussions/305
UPDATE 2
Finally, I have found out what caused the problem to appear in my case. Web app on production server tried to update a status with 140 characters (measured by String.Length property). And the first character was unicode Character 'LEFT-TO-RIGHT MARK' (U+200E). So, this text was passed to TwitterStatus.Update(..) without changes. I debugged a bit Twitterizer sources and noticed that oauth_signature(=hash) was calculated incorrectly. oauth_signature was generated from another url that was actually requested. I haven't cleared the reason why and when this error occurs and maybe will write more information in next few days.
UPDATE 3
I tried to post the same message with new version of Twitterizer (2.3.3) and no error occured. Problem disappeared.
It's the code, that I'm using to post a tweet:
OAuthTokens tokens = new OAuthTokens();
tokens.AccessToken = ConfigurationManager.AppSettings["twitterAccessToken"];
tokens.AccessTokenSecret = ConfigurationManager.AppSettings["twitterAccessTokenSecret"];
tokens.ConsumerKey = ConfigurationManager.AppSettings["twitterAutoPosterConsumerKey"];
tokens.ConsumerSecret = ConfigurationManager.AppSettings["twitterAutoPosterConsumerSecret"];
string text = "Some text";
TwitterResponse<TwitterStatus> tweetResponse = TwitterStatus.Update(tokens, text);
if (tweetResponse.Result == RequestResult.Success)
{
// Tweet posted successfully!
_log.InfoFormat("Posted a tweet #{0}.", tweetResponse.ResponseObject.Id);
}
else
{
_log.ErrorFormat("Error occured while posting a tweet. Result = {0}. ErrorMessage = {1}",
tweetResponse.Result, tweetResponse.ErrorMessage);
}
Please check in the message, if message have apostrophes (') , please replace it with '
Note that ' will count as 5characters.
I think that apostrophes will effect the request package that send to twitter, that make twitter cannot get Token Correctly, so we will got error "Could not authenticate with OAuth".
I had the same trouble. PHP 5.3.1 ran on my local server, while PHP 4.3.2 ran on my production server. I use OAuth library of Google Code obtained from the below,
http://code.google.com/p/oauth/source/browse/#svn%2Fcode%2Fjavascript.
I explored the OAuth header which PHP proxy program received from javascript code on a browser. On my local server, it was
OAuth realm="",oauth_consumer_key="XXX",oauth_token="XXX",oauth_version="1.0",oauth_timestamp="1314956434",oauth_nonce="mF7Tof",oauth_signature_method="HMAC-SHA1",oauth_signature="DbuaiDeMhMYNZ5BaQmOoFr%2FRsEQ%3D"
while on my production server, all the double quotations above were escaped, namely, '\"'.
So I replaced the escaped double quotation to the unescaped one using str_replace function. Then it got work well just the same on my production server. The cause is the difference of the way how double quotation is treated between PHP 5.3.1 and PHP 4.3.2. Escaped double quotation caused an error "Could not authenticate with OAuth."