box / box-windows-sdk-v2

Windows SDK for v2 of the Box API. The SDK is built upon .NET Framework 4.5
https://developer.box.com
Apache License 2.0
186 stars 163 forks source link

JWTAuth Microsoft.IdentityModel.Tokens depencies problem #922

Closed gosztidj closed 1 year ago

gosztidj commented 1 year ago

Hello i have some problem with Box V2 (5.4.0) JWTAuth in C#. ` var reader = new StreamReader("samchully_app_config.json"); var json = reader.ReadToEnd(); var config = BoxConfig.CreateFromJsonString(json);

        var session = new BoxJWTAuth(config);
        var token = await session.AdminTokenAsync();
        BoxClient boxClient = session.AdminClient(token);
        var webLinkUrl = "URL";

        var items = await boxClient.FoldersManager.GetFolderItemsAsync("99073953467",500);`

after var session = new BoxJWTAuth(config); the problem is: System.IO.FileLoadException: 'Microsoft.IdentityModel.Tokens, Version=6.12.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35” The file or assembly or one of its dependencies cannot be loaded. The assembly definition found does not match the assembly reference. (Exception HRESULT: 0x80131040)'

What could be causing the problem?

antusus commented 1 year ago

Hello @gosztidj ,

have you looked for this error reference on-line? https://stackoverflow.com/questions/93879/hresult-0x80131040-the-located-assemblys-manifest-definition-does-not-match-t there are suggestions that there is a difference between what you specified and what you have in your project. Can you try those proposals?

gosztidj commented 1 year ago

Hello @antusus ,

Yes, i tried this error references, but none of these helped.

mwwoda commented 1 year ago

Hi @gosztidj

Could you provide a minimal reproducible sample in the form of a sample project so we can try to reproduce this on our end? Did this also happen in previous versions of the sdk? What kind of .NET version are you running?

There may be several factors that could be causing this problem, please double check @antusus link and possibly do some googling or check SO to try to eliminate the possibility that your local configuration cause this problem.

gosztidj commented 1 year ago

Hi @mwwoda,

I use Console application C# .NET 4.8 version. I had a code written for this in python, but unfortunately it no longer works, so I would like to solve the same method in C#. I would like to download file from box folder. Here is the full code of function what am I trying:

` public static async void DownloadItemsFromUrl() {

        var reader = new StreamReader("app_config.json");
        var json = reader.ReadToEnd();
        var config = BoxConfig.CreateFromJsonString(json);

        var session = new BoxJWTAuth(config);
        var token = await session.AdminTokenAsync();
        BoxClient boxClient = session.AdminClient(token);

        var webLinkUrl = "https://samchully.app.box.com/v/Europe000000";

        var items = await boxClient.FoldersManager.GetFolderItemsAsync("99073953467",500);
        items.Entries.ForEach(i =>
        {
            Console.WriteLine("\t{0}", i.Name);
            if (i.Type == "file")
            {
                var preview_link = adminClient.FilesManager.GetPreviewLinkAsync(i.Id).Result;
               Console.WriteLine("\tPreview Link: {0}", preview_link.ToString());
               Console.WriteLine();
            }   
        });

        Directory.SetCurrentDirectory(Path.Combine(Directory.GetCurrentDirectory(), "Stockinfos", "Samchully");

        DownloadItems(client, sharedFolder);

        Console.WriteLine("Done");

}`

mwwoda commented 1 year ago

I have not been able to reproduce this on my end so far. Would it be possible to provide the code along with the project file (.csproj and possibly .sln). You could isolate the problematic code and get rid of the personal data. It could be the case that your project reference Microsoft.IdentityModel.Tokens multiple times (via e.g dependencies)? If that's the case you could look into binding redirects maybe it could help.

gosztidj commented 1 year ago

Dear @mwwoda ,

I found the solution. 2 things helped with the dependencies problem. One was due to the await Task method.

For the other one, a couple of older version dll files had to be added using the Visual studio Developer console with this solution: https://stackoverflow.com/questions/62764744/could-not-load-file-or-assembly-system-runtime-compilerservices-unsafe

I managed to get the code to work, but unfortunately when I try to download the file I get the following error code. image BoxAPIException: The API returned an error [NotFound | l5uq65hi0xgbw0bp.010d5a0ce9b977ee68c1e8320c4eee4ef] not_found - Could not find the specified resource

Here is the full code: ` DirectoryInfo info = new DirectoryInfo("Stockinfos/Samchully"); string folderName = ""; var localFolderPath = Path.Combine(Directory.GetCurrentDirectory(), folderName); var reader = new StreamReader("samchully_app_config.json"); var json = reader.ReadToEnd(); var config = BoxConfig.CreateFromJsonString(json);

        var session = new BoxJWTAuth(config);
        var token = session.AdminTokenAsync().Result;
        BoxClient boxClient = session.AdminClient(token);
        // Shared URL//
        var webLinkUrl = "https://samchully.app.box.com/v/Europe000000";

        var user = boxClient.UsersManager.GetCurrentUserInformationAsync().Result;
        Console.WriteLine($"User: {user.Id}:{user.Name}");
        Task<BoxItem> getsharedItems = boxClient.SharedItemsManager.SharedItemsAsync(webLinkUrl);

        BoxFolder sharedFolder = (BoxFolder)getsharedItems.Result;
        Console.WriteLine(sharedFolder.Name);
        var items = boxClient.FoldersManager.GetFolderItemsAsync(sharedFolder.Id, 5000, sharedLink: webLinkUrl).Result;

        // How many things are this folder? //
        Console.WriteLine($"TotalCount: {items.TotalCount}");
        string filenamdate = DateTime.Now.AddDays(-1).ToString("_yyyyMMdd");
        foreach (var item in items.Entries)
        {
            if (item.Name.Contains(filenamdate))
            {
                using (FileStream fileStream = new FileStream(localFolderPath + "\\" + item.Name, FileMode.Create, System.IO.FileAccess.Write))
                {
                    Console.WriteLine(item.Name);
                    using (Stream fileContents = boxClient.FilesManager.DownloadAsync(item.Id).Result)
                    {
                        fileContents.CopyToAsync(fileStream);
                    }
                }
                Console.WriteLine("Downloaded File : " + item.Name);
            }

        }`
             using (Stream fileContents = boxClient.FilesManager.DownloadAsync(item.Id).Result) <-- the program stops with an error at this line

What could be causing this? It finds every file in the shared folder perfectly fine.

I use this app for authentication: image

arjankowski commented 1 year ago

Hi @gosztidj,

We're glad you managed to find a solution to the previous problem!

The problem you're writing about here is related to the fact that you're accessing data using the sharedLink: var items = boxClient.FoldersManager.GetFolderItemsAsync(sharedFolder.Id, 5000, sharedLink: webLinkUrl).Result; This way, you gain access to a folder that hasn't been explicitly shared with you.

The problem arises, however, for the download call: boxClient.FilesManager.DownloadAsync(item.Id).Result), where we haven't added support for the shared_link parameter yet -> https://developer.box.com/reference/get-files-id-content/#param-boxapi. Since this file is not directly shared with you and you're not sending the appropriate header, you're receiving a 404.

We've created an internal task for your issue in our internal Jira SDK-3341, and now we need to groom and plan it, then we will come back to you.

In the meantime, if possible, you can create a new user client who is the owner of these files and continue operating on them using that client.

var userID = "FILES_OWNER_USER_ID"
var userToken = session.UserTokenAsync("userID");
var userClient = session.UserClient(userToken.Result, "userID");
using (Stream fileContents = userClient.FilesManager.DownloadAsync(item.Id).Result)
{
    ...
}

Alternatively, you can also use the 'as-user' headers described here -> https://github.com/box/box-windows-sdk-v2/blob/main/docs/authentication.md#as-user

gosztidj commented 1 year ago

Hi @arjankowski,

Unfortunately, the temporary solution you suggested will not work, because the file I want to download changes and is updated every 24 hours, this application will work as an automated process. How long does this parameterization take?

arjankowski commented 1 year ago

Hi @gosztidj,

We managed to solve this problem in this PR, and we have also released a new SDK version 5.5.0 that includes this fix.

So now, when you want to download a file, which you have access to via a shared link, you should call:

boxClient.FilesManager.DownloadAsync(item.Id, sharedLink: webLinkUrl)

Regards, Artur