Possible to have share link expire; not the access grant?

I’d ideally like to generate permanent access grants for each of my users, who in turn might want to generate public share links. I understand I can create restricted access grants with expirations, but I really want to create ephemeral share links from the access grants I create for my users. Is this possible?

My code:

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/joho/godotenv"
	"storj.io/uplink"
)

func main() {
	err := godotenv.Load("../.env")
	if err != nil {
		log.Fatal("Error loading .env file")
	}

	satelliteURL := os.Getenv("STORJ_SATELLITE_ADDRESS")
	apiKey := os.Getenv("STORJ_API_KEY")
	bucketName := os.Getenv("STORJ_BUCKET")
	prefix := "/user123/"
	ctx := context.Background()
        config := edge.Config{
		AuthServiceAddress: "auth.storjshare.io:7777",
	}

	access, err := uplink.RequestAccessWithPassphrase(ctx, satelliteURL, apiKey, "")
	if err != nil {
		log.Fatalf("Could not request access: %v", err)
	}

	permission := uplink.Permission{
		AllowDownload: true,
		AllowUpload:   false,
		AllowList:     false,
		AllowDelete:   false,
	}

	sharePrefix := uplink.SharePrefix{
		Bucket: bucketName,
		Prefix: prefix,
	}

	// Create a derived access grant with the specified permissions and path restriction
	restrictedAccess, err := access.Share(permission, sharePrefix)
	if err != nil {
		log.Fatalf("Could not create restricted access: %v", err)
	}

	// Serialize the restricted access grant to a string
	restrictedAccessGrant, err := restrictedAccess.Serialize()
	if err != nil {
		log.Fatalf("Could not serialize restricted access: %v", err)
	}

		credentials, err := config.RegisterAccess(ctx, restrictedAccessGrant, &edge.RegisterAccessOptions{Public: true})
	if err != nil {
		return "", fmt.Errorf("could not register access: %w", err)
	}

	url, err := edge.JoinShareURL("https://link.storjshare.io", credentials.AccessKeyID, bucketName, "", nil)
	if err != nil {
		return "", fmt.Errorf("could not create a shared link: %w", err)
	}
}

Or, after I give users an access grant, they, in turn, create sub-sub-restricted grants which have expirations?

Hello @abc123456678,
Welcome back!

You can do both.
For uplink CLI:

uplink share --url --not-after=+2h sj://my-bucket/my-prefix/my-file.ext

and only access grant:

uplink share --not-after=+2h sj://my-bucket/my-prefix/my-file.ext

In code you need to specify the time span:

So basically you need to specify NotAfter in the object permission.

1 Like

Thanks for the reply! I guess I still don’t understand where I need to add the NotAfter because it seems like the only place I can specify (in the Go code) is here:

	permission := uplink.Permission{
		AllowDownload: true,
		AllowUpload:   false,
		AllowList:     false,
		AllowDelete:   false,
	}

But if I add it there, doesn’t that expire the access grant itself?

permission := uplink.Permission{
		AllowDownload: true,
		AllowUpload:   false,
		AllowList:     false,
		AllowDelete:   false,
		NotAfter:      parseHumanDateNotAfter('2024-09-01T15:04'),
}

yes, that’s the way how it works. Changing the NotAfter field you would get a new serialized access grant every time, which would be valid until that timestamp.

If you want to have an expiration date for the URL only, but not for the derived access grant, then you need to generate a presigned URL instead: Storj Data Access Methods - Storj Docs, but they can be generated per-object only unlike the access grant and the linksharing URL.

Thanks again for the reply. So in summary, I CANNOT create an expiration URL with a permanent restricted access grant. The only way to set expiration on a URL is to create a pre-signed URL.

I suppose I can generate s3 credentials per user, and use those to generate the pre-signed URL?