.netamazon-s3cloudflareaws-sdk-netcloudflare-r2

Cloudflare R2 presigned url generation with aws sdk .net gives "SigV2 authorization is not supported"


I have the following code (almost the same as this docs page):

private static AmazonS3Client GetS3Client()
{
    var credentials = new BasicAWSCredentials(accessKey, secretKey);
    return new AmazonS3Client(credentials, new AmazonS3Config
    {
        ServiceURL = "xxxx",
    });
}
public static string GeneratePreSignedUrl(string fileName, TimeSpan expiry, string bucketName)
{
    using (AmazonS3Client client = GetS3Client())
    {
        var request = new GetPreSignedUrlRequest
        {
            BucketName = bucketName,
            Key = fileName,
            Verb = HttpVerb.GET,
            Expires = DateTime.UtcNow.Add(expiry),
        };

        return client.GetPreSignedURL(request);
    }
}

If I use AWS S3 (without the ServiceURL) to load an image url, GeneratePreSignedUrl works with no problem and the image is visible in the browser. However, if I use cloudflare R2, visiting the generated url shows the following:

This XML file does not appear to have any style information associated with it. The document tree is shown below.

<Error>
  <Code>Unauthorized</Code>
  <Message>SigV2 authorization is not supported. Please use SigV4 instead.</Message>
</Error>

I don't know what this message means. However, here it says that SigV4 isn't supported?

Also, I have checked that the GetObjectAsync method works, so it's not as if I can't use the aws sdk with R2 at all, but GetPreSignedURL isn't working.

What should I do? Thanks.


Solution

  • I had to do the following:

    private static AmazonS3Client GetS3Client()
    {
        AWSConfigsS3.UseSignatureVersion4 = true;
        var credentials = new BasicAWSCredentials(accessKey, secretKey);
        return new AmazonS3Client(credentials, new AmazonS3Config
        {
            ServiceURL = "https://<your_service_url>",
            SignatureVersion = "v4",
            ForcePathStyle = true,
        });
    }
    

    Did not have to make any change to the request part in my question. So that remained the same:

    public static string GeneratePreSignedUrl(string fileName, TimeSpan expiry, string bucketName)
    {
        using (AmazonS3Client client = GetS3Client())
        {
            var request = new GetPreSignedUrlRequest
            {
                BucketName = bucketName,
                Key = fileName,
                Verb = HttpVerb.GET,
                Expires = DateTime.UtcNow.Add(expiry),
            };
    
            return client.GetPreSignedURL(request);
        }
    }
    

    Thanks to chris05 for part of the answer.