title: Blazor server side - redirecting if unauthenticated before the page starts loading
body: <p>Might be trying to solve this the wrong way, but here's the situation.</p>
  
  <p>I have a component designed to redirect to login if the user trying to access it isn't authenticated, and display not found if they aren't authorized for the page requested.</p>
  
  <pre><code>&lt;AuthorizeViewWithPermissions RequiredPermission="RequiredPermission"&gt;
      &lt;Authorized&gt;
          @ChildContent
      &lt;/Authorized&gt;
      &lt;NotAuthenticated&gt;
          &lt;LoginRedirect /&gt;
      &lt;/NotAuthenticated&gt;
      &lt;NotAuthorized&gt;
          &lt;NotFoundRedirect /&gt;
      &lt;/NotAuthorized&gt;
  &lt;/AuthorizeViewWithPermissions&gt;
  
  @code {
      [Parameter] public RenderFragment ChildContent { get; set; }
  
      [Parameter] public Permissions RequiredPermission { get; set; }
  
      protected override void OnInitialized()
      {
  
      }
  }
  </code></pre>
  
  <p>LoginRedirect is this:</p>
  
  <pre><code>    public class LoginRedirect : ComponentBase
      {
          [Inject] protected NavigationManager NavigationManager { get; set; }
  
          protected override void OnInitialized()
          {
              NavigationManager.NavigateTo("/Login", true);
          }
      }
  </code></pre>
  
  <p>internals of AuthorizeViewWithPermissions:</p>
  
  <pre><code>    /// &lt;summary&gt;
      /// Largely borrowed from the original AuthorizeView, but cut up a bit to use custom permissions and cut out a lot of stuff that isn't needed.
      /// &lt;/summary&gt;
      public class AuthorizeViewWithPermissions : ComponentBase
      {
          private AuthenticationState _currentAuthenticationState;
  
          private bool _isAuthorized;
  
          private bool _isAuthenticated;
  
          /// &lt;summary&gt;
          /// The permission type required to display the content
          /// &lt;/summary&gt;
          [Parameter] public Permissions RequiredPermission { get; set; }
  
          /// &lt;summary&gt;
          /// The content that will be displayed if the user is authorized.
          /// &lt;/summary&gt;
          [Parameter] public RenderFragment&lt;AuthenticationState&gt; ChildContent { get; set; }
  
          /// &lt;summary&gt;
          /// The content that will be displayed if the user is not authorized.
          /// &lt;/summary&gt;
          [Parameter] public RenderFragment&lt;AuthenticationState&gt; NotAuthorized { get; set; }
  
          /// &lt;summary&gt;
          /// The content that will be displayed if the user is not authenticated.
          /// &lt;/summary&gt;
          [Parameter] public RenderFragment&lt;AuthenticationState&gt; NotAuthenticated { get; set; }
  
          /// &lt;summary&gt;
          /// The content that will be displayed if the user is authorized.
          /// If you specify a value for this parameter, do not also specify a value for &lt;see cref="ChildContent"/&gt;.
          /// &lt;/summary&gt;
          [Parameter] public RenderFragment&lt;AuthenticationState&gt; Authorized { get; set; }
  
          /// &lt;summary&gt;
          /// The content that will be displayed while asynchronous authorization is in progress.
          /// &lt;/summary&gt;
          [Parameter] public RenderFragment Authorizing { get; set; }
  
          /// &lt;summary&gt;
          /// The resource to which access is being controlled.
          /// &lt;/summary&gt;
          [Parameter] public object Resource { get; set; }
  
          [CascadingParameter] private Task&lt;AuthenticationState&gt; AuthenticationState { get; set; }
  
          /// &lt;inheritdoc /&gt;
          protected override void BuildRenderTree(RenderTreeBuilder builder)
          {
              // We're using the same sequence number for each of the content items here
              // so that we can update existing instances if they are the same shape
              if (_currentAuthenticationState == null)
              {
                  builder.AddContent(0, Authorizing);
              }
              else if (_isAuthorized)
              {
                  var authorized = Authorized ?? ChildContent;
                  builder.AddContent(0, authorized?.Invoke(_currentAuthenticationState));
              }
              else if (!_isAuthenticated)
              {
                  builder.AddContent(0, NotAuthenticated?.Invoke(_currentAuthenticationState));
              }
              else
              {
                  builder.AddContent(0, NotAuthorized?.Invoke(_currentAuthenticationState));
              }
          }
  
          /// &lt;inheritdoc /&gt;
          protected override async Task OnParametersSetAsync()
          {
              // We allow 'ChildContent' for convenience in basic cases, and 'Authorized' for symmetry
              // with 'NotAuthorized' in other cases. Besides naming, they are equivalent. To avoid
              // confusion, explicitly prevent the case where both are supplied.
              if (ChildContent != null &amp;&amp; Authorized != null)
              {
                  throw new InvalidOperationException($"Do not specify both '{nameof(Authorized)}' and '{nameof(ChildContent)}'.");
              }
  
              if (AuthenticationState == null)
              {
                  throw new InvalidOperationException($"Authorization requires a cascading parameter of type Task&lt;{nameof(AuthenticationState)}&gt;. Consider using {typeof(CascadingAuthenticationState).Name} to supply this.");
              }
  
              // First render in pending state
              // If the task has already completed, this render will be skipped
              _currentAuthenticationState = null;
  
              // Then render in completed state
              // Importantly, we *don't* call StateHasChanged between the following async steps,
              // otherwise we'd display an incorrect UI state while waiting for IsAuthorizedAsync
              _currentAuthenticationState = await AuthenticationState;
              SetAuthorizedAndAuthenticated(_currentAuthenticationState.User);
          }
  
          private void SetAuthorizedAndAuthenticated(ClaimsPrincipal user)
          {
              var userWithData = SessionHelper.GetCurrentUser(user);
  
              _isAuthenticated = userWithData != null;
              _isAuthorized = userWithData?.Permissions.Any(p =&gt; p == RequiredPermission || p == Permissions.SuperAdmin) ?? false;
          }
      }
  </code></pre>
  
  <p>The authentication and authorization checks are working perfectly fine, but the issue is that the page OnInitializedAsync or OnParametersSetAsync fire before the LoginRedirect OnInitialized.</p>
  
  <p>I'm kicking off my calls for data (to an API, that uses a token stored on the logged in user's data) in OnInitializedAsync which results in it attempting to load the data (with no auth token) instead of just redirecting.  If I comment out the data call the redirect works as expected without issue, so it's just a timing/sequence of events issue.</p>
  
  <p>Is there a solution to this? Should I just be changing my api client code to silently fail instead of throwing an unauthorized exception if the auth token is missing?</p>
  
  <p>This is also my app.razor component:</p>
  
  <pre><code>CascadingAuthenticationState&gt;
      &lt;Router AppAssembly="@typeof(Program).Assembly"&gt;
          &lt;Found Context="routeData"&gt;
              &lt;AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"&gt;
                  &lt;NotAuthorized&gt;
                      &lt;LoginRedirect /&gt;
                  &lt;/NotAuthorized&gt;
                  &lt;Authorizing&gt;
                      &lt;p&gt;Checking authorization...&lt;/p&gt;
                  &lt;/Authorizing&gt;
              &lt;/AuthorizeRouteView&gt;
          &lt;/Found&gt;
          &lt;NotFound&gt;
              &lt;LayoutView Layout="@typeof(MainLayout)"&gt;
                  &lt;p&gt;These aren't the droids you're looking for.&lt;/p&gt;
              &lt;/LayoutView&gt;
          &lt;/NotFound&gt;
      &lt;/Router&gt;
  &lt;/CascadingAuthenticationState&gt;
  </code></pre>