Skip to content

Commit d140c15

Browse files
Update info about auth flow now the mechanism has changed
1 parent 3cd0d79 commit d140c15

File tree

1 file changed

+12
-38
lines changed

1 file changed

+12
-38
lines changed

docs/06-authentication-and-authorization.md

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -354,38 +354,19 @@ Next look for the commented-out `.Where` lines in `GetOrders` and `GetOrderWithS
354354

355355
Now if you run the app again, you'll no longer be able to see the existing order details, because they aren't associated with your user ID. If you place a new order with one account, you won't be able to see it from a different account. That makes the application much more useful.
356356

357-
## Ensure authentication before placing or viewing orders
357+
## Enforcing login on specific pages
358358

359-
Now if you're logged in, you'll be able to place orders and see order status. But if you log out then make another attempt to place an order, bad things will happen. The server will reject the `POST` request, causing a client-side exception, but the user won't know why.
359+
Now if you're logged in, you'll be able to place orders and see order status. But if you're not logged in and try to place an order, the flow isn't ideal. It doesn't ask you to log in until you *submit* the checkout form (because that's when the server responds 401 Not Authorized). What if you want to make certain pages require authorization, even before receiving 401 Not Authorized responses from the server?
360360

361-
To fix this on the checkout page, let's make the UI prompt the user to log in (if necessary) as part of placing an order.
361+
You can do this quite easily. In the same way that you use the `[Authorize]` attribute in server-side code, you can use that attribute in client-side Blazor pages. Let's fix the checkout page so that you have to be logged in as soon as you get there, not just when you submit its form.
362362

363-
In the `Checkout` page component, add an `OnInitializedAsync` with some logic to to check whether the user is currently authenticated. If they aren't, send them off to the login endpoint.
363+
By default, all pages allow for anonymous access, but we can specify that the user must be logged in to access the checkout page by adding the `[Authorize]` attribute at the top of `Checkout.razor`:
364364

365-
```cs
366-
@code {
367-
[CascadingParameter] public Task<AuthenticationState> AuthenticationStateTask { get; set; }
368-
369-
protected override async Task OnInitializedAsync()
370-
{
371-
var authState = await AuthenticationStateTask;
372-
if (!authState.User.Identity.IsAuthenticated)
373-
{
374-
// The server won't accept orders from unauthenticated users, so avoid
375-
// an error by making them log in at this point
376-
NavigationManager.NavigateTo("authentication/login?redirectUri=/checkout", true);
377-
}
378-
}
379-
380-
// Leave PlaceOrder unchanged here
381-
}
365+
```razor
366+
@attribute [Authorize]
382367
```
383368

384-
Try it out: now if you're logged out and get to the checkout screen, you'll be redirected to log in. The value for the `[CascadingParameter]` comes from your `AuthenticationStateProvider` via the `CascadingAuthenticationState` you added earlier.
385-
386-
But do you notice something a bit awkward about it? It still shows the checkout UI briefly before the browser loads the login page. We could fix that by wrapping the "checkout" UI inside an `AuthorizeView` like we did in the `LoginDisplay`. But there's an even easier way to ensure that anyone who navigates to the checkout page is logged in. We can enforce that the entire page requires authentication using the router.
387-
388-
To set this up, update *App.razor* to render an `AuthorizeRouteView` instead of a `RouteView` when the route is found.
369+
Next, to make the router respect such attributes, update *App.razor* to render an `AuthorizeRouteView` instead of a `RouteView` when the route is found.
389370

390371
```razor
391372
<CascadingAuthenticationState>
@@ -411,15 +392,7 @@ To set this up, update *App.razor* to render an `AuthorizeRouteView` instead of
411392

412393
The `AuthorizeRouteView` will route navigations to the correct component, but only if the user is authorized. If the user is not authorized, the `NotAuthorized` content is displayed. You can also specify content to display while the `AuthorizeRouteView` is determining if the user is authorized.
413394

414-
By default, all pages allow for anonymous access, but we can specify that the user must be logged in to access the checkout page by adding the `[Authorize]` attribute. You add attributes to a component using the `@attribute` directive.
415-
416-
Update the `Checkout`, `MyOrders`, and `OrderDetails` pages to add the `[Authorize]` attribute;
417-
418-
```razor
419-
@attribute [Authorize]
420-
```
421-
422-
Now when you try to nativgate to any of these pages while signed out, you see the `NotAuthorized` content we setup in *App.razor*.
395+
Now when you try to nativgate to the checkout page while signed out, you see the `NotAuthorized` content we setup in *App.razor*.
423396

424397
![Not authorized](https://user-images.githubusercontent.com/1874516/78410504-63b27880-75c1-11ea-8c2c-ab62c1c24596.png)
425398

@@ -461,7 +434,9 @@ Then replace the `NotAuthorized` content in *App.razor* with the `RedirectToLogi
461434
</CascadingAuthenticationState>
462435
```
463436

464-
If you now try to access the "myorders" page while signed out, you are redirected to the login page. And once the user is logged in, they are redirected back to the page they were trying to access thanks to the `returnUrl` parameter.
437+
If you now try to access the checkout page while signed out, you are redirected to the login page. And once the user is logged in, they are redirected back to the page they were trying to access thanks to the `returnUrl` parameter.
438+
439+
## Hiding navigation options depending on authorization status
465440

466441
It's a bit unfortunate that users can see the My Orders tab when they are not logged in. We can hide the My Orders tab for unauthenticated users using the `AuthorizeView` component.
467442

@@ -478,9 +453,8 @@ Update `MainLayout` to wrap the My Orders `NavLink` in an `AuthorizeView`.
478453

479454
The My Orders tab should now only be visible when the user is logged in.
480455

481-
We've now seen that there are three basic ways to interact with the authentication/authorization system inside components:
456+
We've now seen two ways to interact with the authentication/authorization system inside components:
482457

483-
* Receive a `Task<AuthenticationState>` as a cascading parameter. This is useful when you want to use the `AuthenticationState` in procedural logic such as an event handler.
484458
* Wrap content in an `AuthorizeView`. This is useful when you just need to vary some UI content according to authorization status.
485459
* Place an `[Authorize]` attribute on a routable component. This is useful if you want to control the reachability of an entire page based on authorization conditions.
486460

0 commit comments

Comments
 (0)