loading
Note:
Only matters inside a cross-site iframe In a top-level page - like this one - there is nothing to ask for: HasAccess answers true and Request is unnecessary. This API is for the case where your Blazor app is embedded in someone else's site, where the browser hands it a fresh, empty storage jar per embedding site and any auth cookie set on its own domain is invisible.

Support and current state

IsSupported / HasAccess

HasAccess answers true on engines that don't partition storage at all, since there is nothing to be denied - which means a false genuinely means 'ask'. Check it before prompting: browsers count an unnecessary prompt against you.

C#
@inject Bit.Butil.StorageAccess storageAccess

var supported = await storageAccess.IsSupported();

if (await storageAccess.HasAccess() is false)
{
    // show a button - Request needs a user gesture
}
Live sample
Supported Not checked.
Has access Not checked.
state output
Results will appear here when you interact with the samples.

Ask for access

Request

Must be called from a user-gesture handler, and browsers generally only grant it for a site the user has already interacted with at the top level. False covers every refusal - user declined, no gesture, embedder's permissions policy forbids it - because the spec deliberately doesn't say which. A grant lasts for the rest of this document's lifetime, not permanently, so ask again after a reload.

Razor
@inject Bit.Butil.Cookie cookie
@inject Bit.Butil.StorageAccess storageAccess

@* Must be a real user gesture: without one the request is refused, and the refusal is remembered. *@
<button @onclick="Ask">Continue</button>

@code {
    private async Task Ask()
    {
        var granted = await storageAccess.Request();
        if (granted)
        {
            // unpartitioned cookies and storage are now readable
            var token = await cookie.GetValue("auth");
        }
        else
        {
            // fall back: an in-frame sign-in, or a popup to the top-level origin
        }
    }
}
Live sample
request output
Results will appear here when you interact with the samples.

Where this fits

-

Once access is granted, nothing else changes: Cookie, LocalStorage, SessionStorage and IndexedDb all start seeing the unpartitioned jar. The Storage Access API is a gate in front of the storage APIs, not a replacement for them.

Razor
@inject Bit.Butil.LocalStorage localStorage
@inject Bit.Butil.StorageAccess storageAccess

@if (_needsGesture)
{
    <button @onclick="Ask">Continue</button>
}

@code {
    private bool _needsGesture;

    // The usual pattern for an embedded app.
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender is false) return;

        if (await storageAccess.IsSupported() && await storageAccess.HasAccess() is false)
        {
            // Render a "Continue" button rather than calling Request on load - without a gesture it
            // is refused, and the refusal is remembered.
            _needsGesture = true;
            StateHasChanged();
            return;
        }

        // from here on, the ordinary storage wrappers see the real jar:
        var session = await localStorage.GetItem("session");
    }

    private async Task Ask() => _needsGesture = await storageAccess.Request() is false;
}
Warning:
Don't ask on loadRequest outside a user gesture is refused, and some engines treat a refused request as a signal not to prompt again for a while. Render a button, and call it from the click.

API reference

Member
Signature
Description
IsSupported
ValueTask<bool> IsSupported()
True when the runtime exposes document.requestStorageAccess. Returns default (false) during prerender/SSR instead of throwing.
HasAccess
ValueTask<bool> HasAccess()
Whether this document already has unpartitioned storage. True on engines that don't partition at all, so a false genuinely means 'ask'.
Request
ValueTask<bool> Request()
Asks for access. Requires a user gesture. False covers every refusal - the spec deliberately gives no reason. A grant lasts for this document's lifetime only.
IsRequestForSupported
ValueTask<bool> IsRequestForSupported()
True when the runtime exposes document.requestStorageAccessFor (Chromium only).
RequestFor
ValueTask<bool> RequestFor(string origin)
The top-level counterpart of Request: a first-party page asks for storage access on behalf of an origin it embeds, saving the embedded frame from needing its own user gesture. Call it from the top-level page, not the iframe.
An unhandled error has occurred. Reload 🗙