Advertisement

#13 Main Navigation (Authentication)

In this article we will focus on adding the authentication links. For this project that includes the ability for the user to register and login. If they are authenticated they will then have the ability to visit their account page and to logout. In the case of logging out we will use a form and see how to style it to look like all of the other links as well as how to include the anti-forgery token when creating a reusable variable as we have been doing.

More Icons

  • WebUi
    • Source
      • main.site.ts

For our authentication links I want to use a few more icons so we will start by adding them to our library (a).

main.site.ts

...
import { faEdit } from "@fortawesome/free-solid-svg-icons/faEdit";
import { faSignInAlt } from "@fortawesome/free-solid-svg-icons/faSignInAlt";
import { faSignOutAlt } from "@fortawesome/free-solid-svg-icons/faSignOutAlt";
import { faUser } from "@fortawesome/free-solid-svg-icons/faUser";

library.add(
    ...
    faEdit,
    faSignInAlt,
    faSignOutAlt,
    faUser,
);
...
(a) Adding some addition icons from font awesome to our library for use with our authentication links.

Adding more links

  • WebUi
    • Pages
      • Shared
        • _MainNav.cshtml

Now that we have some more icons it is time to use a couple of them. Since we want to use some icons with these links we will add a LinkIcon func and modify the LinkText func. With that change done we need to update the Articles and Applications and add the Login and Register (b).

_MainNav.cshtml

...
@{
    ...
    var LinkIcon = new Func<string, string>((icon) => $"<i class=\"fas fa-{icon} link-icon\"></i>");
    var LinkText = new Func<..., string>((..., icon) => $"<div class=\"...\">{icon}<span>...</span></div>");
    ...
    var Articles = Html.Raw(Li(Anchor(..., LinkText(..., ""))));
    var Applications = Html.Raw(Li(Anchor(..., LinkText(..., ""))));
    ...
    var Login = Html.Raw(Li(Anchor("/identity/login", LinkText("Login", LinkIcon("sign-in-alt")))));
    var Register = Html.Raw(Li(Anchor("/identity/register", LinkText("Register", LinkIcon("edit")))));
}

<header>
    <nav>
        ...
        <div class="authentication">
            <ul>
                @Register
                @Login
            </ul>
        </div>
    </nav>
</header>
(b) Modifications need in our markup to generate authentication links that include icons.

Styling the authentication list elements

  • WebUi
    • Source
      • components
        • main-nav
          • main-nav.component.scss

Now it is time to add just a little bit of styling and set the grid area of our authentication links (c).

main-nav.component.scss

...
header {
    ...
    grid-template-areas: "... authentication";
    grid-template-columns: auto auto auto;
    ...
    @include media-gt($mobile-break-width) {
        grid-template-areas: "... authentication";
        grid-template-columns: ... auto;
    }
    ...
    .authentication {
        grid-area: authentication;
        display: none;

        @include media-gt($mobile-break-width) {
            display: block;
        }

        .link-icon {
            margin-right: 0.25em;
        }
    }
}
(c) Adding some styling to our authentication list elements and setting the grid area.
Advertisement

What if we are authenticated?

  • WebUi
    • Pages
      • Shared
        • _MainNav.cshtml

We have taken care of being able to register and login but we need a couple more links if the user is already authenticated. We will start by adding a Account func just like all of the others and we will hard code in a form for allowing the user to logout temporarily (d).

_MainNav.cshtml

...
@{
    ...
    var isAuthenticated = !User.Identity.IsAuthenticated;
    ...
    var Account = Html.Raw(Li(Anchor("/identity/account", LinkText("Account", LinkIcon("user")))));
    ...
}

<header>
    <nav class="main-navigation">
        ...
        <div class="authentication">
            <ul>
                @if (isAuthenticated)
                {
                    @Account
                    <form action="/identity/logout" method="post">
                        @Html.AntiForgeryToken()
                        <button type="submit">
                            <i class="fas fa-sign-out-alt link-icon"></i>
                            <span>Logout</span>
                        </button>
                    </form>
                }
                else
                {
                    @Register
                    @Login
                }
            </ul>
        </div>
    </nav>
</header>
(d) Time to add an if statement based on whether the user is authenticated that will display either the account and logoff links or the register and login links.

Style the form

  • WebUi
    • Source
      • components
        • main-nav
          • main-nav.component.scss

Now that we have the form in place for logging out I would like to style it to look like all of the other links (e).

main-nav.component.scss

...
$action-color: #0984e3 !default;
...
header {
    .authentication {
        ...
        form {
            display: flex;
            align-items: center;
            height: 100%;

            button {
                background: none;
                border: none;
                color: $navigation-anchor-color;
                height: 100%;
                @include padding(null em(10px));
                cursor: pointer;
                font-weight: 400;
        
                &:hover {
                    background: none;
                    color: $action-color;
                }
            }
        }
    }
}
(e) Styling the form so that it fits in with all of the other links.

Hard coding is bad

  • WebUi
    • Pages
      • Shared
        • _MainNav.cshtml

As I have said previously the reason we are approaching our main navigation they way we are is so that we can define our links once and add them to the markup as many times as we like at any place we like. To stick with this approach we need to handle the form that we previously added. Since the only other form we will use is for the search functionality and it will only be located in one place we will not create a separate form func (f).

_MainNav.cshtml

@using System.IO
@using System.Text.Encodings.Web
...
@{
    ...
    var writer = new StringWriter();
    Html.AntiForgeryToken().WriteTo(writer, HtmlEncoder.Default);
    var antiForgeryToken = writer.ToString();
    ...
    var Logout = Html.Raw($"<form action=\"/identity/logout\" method=\"post\">{antiForgeryToken}<button type=\"submit\">{LinkIcon("sign-out")}<span>Logout</span></button></form>");
}

<header>
    <nav class="main-navigation">
        ...
        <div class="authentication">
            <ul>
                @if (isAuthenticated)
                {
                    ...
                    @Logout
                }
                else
                {
                    ...
                }
            </ul>
        </div>
    </nav>
</header>
(f) Converting our hard coded logout markup to a reusable an IHtmlContent variable.

Redirecting the user

  • WebUi
    • Pages
      • Shared
        • _MainNav.cshtml

The last thing we want to accomplish in this article is to have the ability to redirect the user back to whatever page they were viewing when they decide to either login or register (g).

_MainNav.cshtml

@using System.Net
...
@{
    ...
    var redirectUrl = "/";
    var path = Context.Request.Path;
    if (path.HasValue && path.Value.Contains("error") == false && path.Value.Contains("identity") == false)
    {
        redirectUrl = path.Value;
    }
    var redirectQueryString = $"?redirectUrl={WebUtility.UrlEncode(redirectUrl)}";
    
    var Login = Html.Raw(Li(Anchor($"/identity/login{redirectQueryString}", ...)));
    var Register = Html.Raw(Li(Anchor($"/identity/register{redirectQueryString}", ...)));
}
...
(g) Adding the ability to know what page the user should be redirected back to if they if they choose to either login or register.
Exciton Interactive LLC
Advertisement