Yes — I ran into the exact same issue a while back, and I totally understand how confusing it can be when search suddenly stops working after enabling Restrict Public Access. I searched everywhere for a ready-made solution, but didn’t find much at the time, so I ended up implementing a workaround myself.
In short, the problem is that when you restrict public access, Umbraco’s indexer (especially when using something like the FullTextSearch package) no longer has permission to render and index the protected pages — which causes your search results to go empty.
My solution was to programmatically log in a special “search user” during the indexing process. I created a secure API endpoint that allows the indexer (via an HttpClient) to log in this user, retrieve the authentication cookie, and use it when rendering pages to be indexed. This ensures the indexer gets access to the full content — even behind login.
Some key points of the approach:
I defined login credentials and a role for this search user in config.
During indexing, a request is made to an internal API to authenticate the user.
The auth cookie from this login is attached to the indexing HTTP request.
The pages are rendered as if viewed by an authenticated member with proper group access.
This gives the indexer everything it needs without exposing protected content to the public.
I used Umbraco 13.6.0 and the FullTextSearch package — which allows for custom implementations like this via the IPageRenderer interface.
It took a bit of setup (custom services, dependency injection, etc.), but once it’s in place, it works reliably and respects your member protection.
The above answer already points out that restricted content is not indexed by default. However, no difficult workarounds are needed to make this work. You can simply allow your external index to also index restricted content. What you need for that is a custom ContentValueSetValidator.
You can configure that like this for example:
public class ConfigureExternalIndexWithRestrictedAccess
: IConfigureNamedOptions<LuceneDirectoryIndexOptions>
{
public void Configure(LuceneDirectoryIndexOptions options)
{
}
public void Configure(string? name, LuceneDirectoryIndexOptions options)
{
if (!string.Equals(name, "ExternalIndex", StringComparison.Ordinal))
return;
// 👇 this particular constructor overload automatically enables protected content
options.Validator = new ContentValueSetValidator(
publishedValuesOnly: true);
}
}
public class MyComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.ConfigureOptions<ConfigureExternalIndexWithRestrictedAccess>();
}
}