gochuck
gochuck

Reputation: 205

S3 SignedURL fails

I'm trying to create a signed URL for a GET object request in S3. I have this code working flawlessly for putting objects in S3 but I can't seem to get it to work for GET. I sign the URL with this code

    //Create the signed url using the company id
func (user *User) signURLForUser(sess *session.Session) (*URLSign, error) {
    svc := s3.New(sess)
    svc.Config.Region = aws.String(os.Getenv("REGION"))
    req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
        Bucket: aws.String("bucket"),
        Key:    aws.String(user.CompanyID + "/" + user.FileRequest),
    })
    var urlSign URLSign
    //urlSign.Size = *out.ContentLength
    str, err := req.Presign(time.Minute * 60 * 24 * 5) //Expire in 5 days
    if err != nil {
        log.Println("Error signing URL Request")
        return nil, err
    }
    urlSign.URL = str
    return &urlSign, nil
}

But when I try to use the URL it returns I get this error:

 <Error>
<Code>AuthorizationQueryParametersError</Code>
<Message>X-Amz-Algorithm only supports "AWS4-HMAC-SHA256"</Message>
<RequestId>9D7CFB14B195A260</RequestId>
<HostId>
Dgh+SqrHbrdKcbkCYrAj3nObLMAwS7k5+VR1zwC/8ZMS3S4++IAAEXXh3zMZ3CpOAyxX1Kc7Opg=
</HostId>
</Error>

I've check the IAM permissions, they're set for GetObject. I can't think of what else I'm doing wrong.

EDIT: Here's an example of the URL For sure: https://rsmachiner-user-code.s3.amazonaws.com//CFDMP_ServoGear.gcode?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAVEENPDKJRUDZKEVM%2F20180812%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180812T005443Z&X-Amz-Expires=432000&X-Amz-Security-Token=FQoGZXIvYXdzEBoaDIVdv9t408gWWi9vvSLjAaa0pZNA%2BXu83%2FFSyng4XvFdv5%2B7nRB%2FQydMLyi%2BBS84yXqwP6VYn7VlInw4ip1M0lkjHRXQf8OAvQLPrIl%2FQZoTe%2Fy3N6bqhLDOnFVJ3UZzYDQ4%2FbX%2Brc6mvVbkhRsQPiarKBuLYDiOD%2FNoSaItMwI9FsMDknw1qX0Pf%2BZ5La0GmanHrTt9YUI01cIUKJ40No5mKJIwcXw3%2F5QOpUc59rZ2zEzlWP9OXeEwWKp%2Bog5P0v7ABX1lRPsCx4HGEstKhw3ZWmJfQhAcAvhrjmXIMqGNKkaCI5L0ap23jf4GvPMGd4%2BcKIKKvtsF&X-Amz-SignedHeaders=host&X-Amz-Signature=82dfb9b392b5e1ef44c7140259ad884e696b48f8094bdd2d223b8650ebdf59f7

Upvotes: 4

Views: 8613

Answers (2)

baduker
baduker

Reputation: 20052

I had the exact same issue when building a lambda and API Gateway integration in Go.

I used a custom JSON encoder and didn't realize it used HTML-escapes.

func jsonResponse(status int, body interface{}) APIGatewayResponse {
    // Use a custom Encoder that disables HTML escaping -> this created the issue with \u2026 instead of the &
    buf := new(bytes.Buffer)
    enc := json.NewEncoder(buf)
    enc.SetEscapeHTML(false) // This is key to keep the pre-sign url working
    if err := enc.Encode(body); err != nil {
        return errorResponse(500, err.Error())
    }

    return APIGatewayResponse{
        StatusCode: status,
        Body:       buf.String(),
        Headers:    map[string]string{"Content-Type": "application/json"},
    }
}

I was embedding the \u0026–escaped JSON as the raw string in the Body initially. The client that made the request just saw the \u0026 instead of decoding the JSON again, which made the presigned URL malformed.

Upvotes: 0

user1805241
user1805241

Reputation: 161

Such issues occur when you are not correctly specifying the algorithm. For me, I was using this url: https://s3_endpoint?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026 which returned to me the same error. I replaced the \u0026 with & and it worked fine.

Upvotes: 15

Related Questions