erotik film
bodyheat full moves www xxx kajal video la figa che sborra ver video de sexo porno
Luxury replica watches
sex
film izle film izle casino siteleri tipobet giris
asyabahis
escort antalya

When you buy this book you support this site! - Thank You for your support!

Dec 18

Written by: Michael Washington
12/18/2019 6:13 AM  RssIcon

 

To demonstrate how authentication works in a server-side Blazor application, we will strip authentication down to its most basic elements. We will simply set a cookie then read that cookie in the application.

 

Application Authentication

image

Most business web applications require their users to log into the application.

 

image

The user enters their username and password, that are checked against a membership database.

 

image

Once authenticated, the application recognizes the user and now has the ability to deliver content securely.

Once the authentication process of a server-side Blazor application is understood, we can then implement an authentication and membership management system that meets our needs (for example, one that allows users to create and manage their user accounts).

NOTE: This sample code does not check to see if a person is using a legitimate username and password! You would need to add the proper code to check. This code is just a demonstration of how the process of authorizing a user works.

For a complete application see: Creating A Step-By-Step End-To-End Database Server-Side Blazor Application.

 

Create The Application

image

Open Visual Studio 2019.

 

image

Create a Blazor Server App without authentication.

 

Add Nuget Packages

image

In the Solution Explorer, right-click on the client project and select Manage NuGet Packages.

 

image

Add references to the following libraries:

  • Microsoft.AspNetCore.Authorization
  • Microsoft.AspNetCore.Http
  • Microsoft.AspNetCore.Identity

 

image

And:

  • Microsoft.AspNetCore.Blazor.HttpClient

 

 

Add Cookie Authentication

image

Open the Startup.cs file.

Add the following using statements to the top of the file:

 

// ******
// BLAZOR COOKIE Auth Code (begin)
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using System.Net.Http;
// BLAZOR COOKIE Auth Code (end)
// ******
 

Alter the Startup class to the following, adding the sections marked BLAZOR COOKIE Auth Code:

 

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }
        // This method gets called by the runtime. Use this method to 
        // add services to the container.
        // For more information on how to configure your application, 
        // visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            // ******
            // BLAZOR COOKIE Auth Code (begin)
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(
                CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie();
            // BLAZOR COOKIE Auth Code (end)
            // ******
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddSingleton<WeatherForecastService>();
            // ******
            // BLAZOR COOKIE Auth Code (begin)
            // From: https://github.com/aspnet/Blazor/issues/1554
            // HttpContextAccessor
            services.AddHttpContextAccessor();
            services.AddScoped<HttpContextAccessor>();
            services.AddHttpClient();
            services.AddScoped<HttpClient>();
            // BLAZOR COOKIE Auth Code (end)
            // ******
        }
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. 
                // You may want to change this for production scenarios, 
                // see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseRouting();
            // ******
            // BLAZOR COOKIE Auth Code (begin)
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseAuthentication();
            // BLAZOR COOKIE Auth Code (end)
            // ******
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }

 

 

First the code adds support for cookies. Cookies are created by the application, and passed to the user’s web browser when the user logs in. The web browser passes the cookie back to the application to indicate that the user is authenticated. When the user ‘logs out’, the cookie is removed.

This code also adds:

  • HttpContextAccessor
  • HttpClient

as services that will be accessed in the code using dependency Injection.

See this link for a full explanation of how HttpContextAccessor allows us to determine who the logged in user is.

 

Add Login/Logout Pages

image

Logging in (and out) is performed by .cshtml pages.

Add the following Razor pages and code:

 

Login.cshtml

 

@page
@model BlazorCookieAuth.Server.Pages.LoginModel
@{
    ViewData["Title"] = "Log in";
}
<h2>Login</h2>
 

 

Login.cshtml.cs

 

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace BlazorCookieAuth.Server.Pages
{
    [AllowAnonymous]
    public class LoginModel : PageModel
    {
        public string ReturnUrl { get; set; }
        public async Task<IActionResult> 
            OnGetAsync(string paramUsername, string paramPassword)
        {
            string returnUrl = Url.Content("~/");
            try
            {
                // Clear the existing external cookie
                await HttpContext
                    .SignOutAsync(
                    CookieAuthenticationDefaults.AuthenticationScheme);
            }
            catch { }
            // *** !!! This is where you would validate the user !!! ***
            // In this example we just log the user in
            // (Always log the user in for this demo)
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, paramUsername),
                new Claim(ClaimTypes.Role, "Administrator"),
            };
            var claimsIdentity = new ClaimsIdentity(
                claims, CookieAuthenticationDefaults.AuthenticationScheme);
            var authProperties = new AuthenticationProperties
            {
                IsPersistent = true,
                RedirectUri = this.Request.Host.Value
            };
            try
            {
                await HttpContext.SignInAsync(
                CookieAuthenticationDefaults.AuthenticationScheme,
                new ClaimsPrincipal(claimsIdentity),
                authProperties);
            }
            catch (Exception ex)
            {
                string error = ex.Message;
            }
            return LocalRedirect(returnUrl);
        }
    }
}

 

Logout.cshtml

 

@page
@model BlazorCookieAuth.Server.Pages.LogoutModel
@{
    ViewData["Title"] = "Logout";
}
<h2>Logout</h2>

 

Logout.cshtml.cs

 

using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace BlazorCookieAuth.Server.Pages
{
    public class LogoutModel : PageModel
    {
        public async Task<IActionResult> OnGetAsync()
        {
            // Clear the existing external cookie
            await HttpContext
                .SignOutAsync(
                CookieAuthenticationDefaults.AuthenticationScheme);
            return LocalRedirect(Url.Content("~/"));
        }
    }
}

 

Add Client Code

image

Add a page called LoginControl.razor to the Shared folder using the following code:

 

@page "/loginControl"
@using System.Web;
<AuthorizeView>
    <Authorized>
        <b>Hello, @context.User.Identity.Name!</b>
        <a class="ml-md-auto btn btn-primary"
           href="/logout?returnUrl=/"
           target="_top">Logout</a>
    </Authorized>
    <NotAuthorized>
        <input type="text"
               placeholder="User Name"
               @bind="@Username" />
        &nbsp;&nbsp;
        <input type="password"
               placeholder="Password"
               @bind="@Password" />
        <a class="ml-md-auto btn btn-primary"
           href="/login?paramUsername=@encode(@Username)&paramPassword=@encode(@Password)"
           target="_top">Login</a>
    </NotAuthorized>
</AuthorizeView>
@code {
    string Username = "";
    string Password = "";
    private string encode(string param)
    {
        return HttpUtility.UrlEncode(param);
    }
}

 

This code creates a login component that uses the AuthorizeView component to wrap markup code based on the user’s current authentication.

If the user is logged in, we display their name and a Logout button (that navigates the user to the logout page created earlier).

If they are not logged in, we display username and password boxes and a Login button (that navigates the user to the login page created earlier).

 

image

Finally, we alter the MainLayout.razor page (in the Shared folder) to the following:

 

@inherits LayoutComponentBase
<div class="sidebar">
    <NavMenu />
</div>
<div class="main">
    <div class="top-row px-4">
        <!-- BLAZOR COOKIE Auth Code (begin) -->
        <LoginControl />
        <!-- BLAZOR COOKIE Auth Code (end) -->
    </div>
    <div class="content px-4">
        @Body
    </div>
</div>

 

This adds the login component to the top of every page in the Blazor application.

 

image

Open the App.razor page and surround all the existing code in a CascadingAuthenticationState tag.

 

image

We can now hit F5 to run the application.

 

image

We can enter a username and password and click the Login button…

 

image

We can then look in the Google Chrome Web Browser DevTools and see the cookie has been created.

 

image

When we click Logout

 

image

The cookie is removed.

 

Calling Server Side Controller Methods

At this point all the .razor pages will properly detect if the user is authenticated, and operate as expected. However, if we make a http request to a server side controller, the authenticated user will not be properly detected.

 

image

To demonstrate this, we first open the startup.cs page and add the following code to the end of the app.UseEndpoints method, (under the endpoints.MapFallbackToPage("/_Host"); line), to allow http requests to controllers to be properly routed:

 

        // ******
        // BLAZOR COOKIE Auth Code (begin)
        endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
        // BLAZOR COOKIE Auth Code (end)
        // ******

 

 

image

Next, we create a Controllers folder and add a UserController.cs file with the following code:

 

using Microsoft.AspNetCore.Mvc;
namespace BlazorCookieAuth.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : Controller
    {
        // /api/User/GetUser
        [HttpGet("[action]")]
        public UserModel GetUser()
        {
            // Instantiate a UserModel
            var userModel = new UserModel
            {
                UserName = "[]",
                IsAuthenticated = false
            };
            // Detect if the user is authenticated
            if (User.Identity.IsAuthenticated)
            {
                // Set the username of the authenticated user
                userModel.UserName = 
                    User.Identity.Name;
                userModel.IsAuthenticated = 
                    User.Identity.IsAuthenticated;
            };
            return userModel;
        }
    }
    // Class to hold the UserModel
    public class UserModel
    {
        public string UserName { get; set; }
        public bool IsAuthenticated { get; set; }
    }
}

 

image

We add a new .razor page, CallServerSide.razor, using the following code:

 

@page "/CallServerSide"
@using BlazorCookieAuth.Controllers
@using System.Net.Http
@inject HttpClient Http
@inject NavigationManager UriHelper
@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
<h3>Call Server Side</h3>
<p>Current User: @CurrentUser.UserName</p>
<p>IsAuthenticated: @CurrentUser.IsAuthenticated</p>
<button class="btn btn-primary" @onclick="GetUser">Get User</button>
@code {
    UserModel CurrentUser = new UserModel();
    async Task GetUser()
    {
        // Call the server side controller
        var url = UriHelper.ToAbsoluteUri("/api/User/GetUser");
        var result = await Http.GetJsonAsync<UserModel>(url.ToString());
        // Update the result
        CurrentUser.UserName = result.UserName;
        CurrentUser.IsAuthenticated = result.IsAuthenticated;
    }
}

 

Finally, we use the following code to add a link to the page in Shared/NavMenu.razor:

 

        <li class="nav-item px-3">
            <NavLink class="nav-link" href="CallServerSide">
                <span class="oi oi-list-rich" aria-hidden="true"></span> Call Server Side
            </NavLink>
        </li>

 

 

 

image

We run the application and log in.

 

image

We navigate to the new Call Server Side control and click the Get User button (that calls the UserController.cs that we just added), and it does not detect the logged in user.

To resolve this, change the GetUser method in the CallServerSide.razor page to the following:

 

    async Task GetUser()
    {
        // Code courtesy from Oqtane.org (@sbwalker)
        // We must pass the authentication cookie in server side requests
        var authToken =
        HttpContextAccessor.HttpContext.Request.Cookies[".AspNetCore.Cookies"];
        if (authToken != null)
        {
            Http.DefaultRequestHeaders
            .Add("Cookie", ".AspNetCore.Cookies=" + authToken);
            // Call the server side controller
            var url = UriHelper.ToAbsoluteUri("/api/User/GetUser");
            var result = await Http.GetJsonAsync<UserModel>(url.ToString());
            // Update the result
            CurrentUser.UserName = result.UserName;
            CurrentUser.IsAuthenticated = result.IsAuthenticated;
        }
    }

 

We have an authentication cookie, we just need to pass it in the DefaultRequestHeaders.

 

image

Now, when we log in, and click the Get User button, the controller method is able to detect the logged in user.

 

Special Thanks

This article would not be possible without sample code (using the full .Net Core Membership provider) provided by SQL-MisterMagoo.

Additional research provided by Shaun Walker.

 

Links

Blazor.net

Use cookie authentication without ASP.NET Core Identity

ASP.NET Core Blazor authentication and authorization

BlazorTest (SQL-MisterMagoo's site)

Authentication for serverside Blazor (How to use IHttpContextAccessor)

Blazor Security/Authorization

 

Download

The project is available at http://Blazorhelpwebsite.com/Downloads.aspx

You must have Visual Studio 2019 (or higher) installed to run the code.

Tags: Blazor
Categories:

25 comment(s) so far...


Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

How to authentication with account in database sql server?

By tumbal on   12/28/2019 5:31 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@tumbal - For an example of authentication with account in database sql server see: http://blazorhelpwebsite.com/Blog/tabid/61/EntryId/4318/Creating-A-Step-By-Step-End-To-End-Database-Server-Side-Blazor-Application.aspx

By Michael Washington on   12/28/2019 5:32 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

Thanks,

that was really helpful!
The key is to mix Razor Pages for SignIn/SignOut with a Blazor app.
I needed this for a simple way to temporary secure a proof-of-concept cloud app. In the future, I will use ASP.NET Identity together with Blazor.

By Sven on   1/16/2020 7:24 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

It would also be great if you could share the demo project on Github.

By Sven on   1/16/2020 7:24 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@Sven - All code is on the downloads page. I don't sell my email list. I only send out a few emails a year mostly about my book launches. It is how I pay for the servers. All emails have an 'unsubscribe' link.

By Michael Washington on   1/16/2020 7:26 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@MichaelWashington, why is it necessary to repeat app.UseHttpsRedirection() and app.UseStaticFiles() in Configure()? Intuitively one would think these calls would only need to be made once.

By PM on   1/17/2020 10:50 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@PM - They may not be needed. I added them because they were in the example provided by Microsoft in their non Blazor .Net Core example that this code was based on. My code works, but the lines may not be needed for Blazor. They *are* needed for MVC apps. If a Blazor app has MVC pages those lines are needed.

By Michael Washington on   1/17/2020 10:52 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

I used this in my project and it works perfect in development but when I published,got an error - httpContextAccessor is Null when I try to get authToken. Do you have any idea how to fix this?

By Irakli on   1/22/2020 4:57 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@Irakli - You may need extra configuration if using IIS. I only tested this deploying on Azure.

By Michael Washington on   1/22/2020 4:59 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

yes, I'm using IIS and it's not working. did several things but no success.

By Irakli on   1/22/2020 5:26 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@Irakli - I retested it using Azure (I was concerned that the recent Google web browser "same site" cookie policy change my have affected something), but, it works fine.

By Michael Washington on   1/22/2020 5:28 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

finally I did it. I just added some new features in my IIS , I dont know which one worked exactly but maybe it was web sockets feature. thanks for your attention.

By Irakli on   1/22/2020 8:34 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

I have some problems using this solution.
If you call GetUser () many times quickly, you will get a 400 bad request error.
How can I solve this problem?

By ljh on   1/27/2020 3:25 PM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@ljh - All I can think of is your development machine or your web server cannot handle the traffic. Increasing your server resources should resolve the issue.

By Michael Washington on   1/27/2020 3:29 PM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

Thanks for this sample - helped me a lot.

But I got stuck at one point: I'm trying to change login method from GET with user/password in parameters to POST with user/password from form (which is kind of mandatory for real-world application).

I added a form (EditForm) in LoginControl.razor. On submit, I make Http.PostAsync with JSON-encoded form content.

In Login.cshtml.cs, I added handler like:
public async Task OnPostAsync([FromBody] LoginRequest request)

Where "LoginRequest" is my username/password model object.
The handler receives login-request data correctly and does exactly same SignInAsync-stuff as your original "GET" handler.

But the content annotated as " " is not displayed - I still have the content annotated as " displayed.

What am I doing wrong? Any hints how to covert this sample to POSTing login data?
TIA

By Maciej Maczynski on   1/29/2020 4:36 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@Maciej Maczynski - If using https the communication is still 'safe'. However, if you want to use a post for the login, direct the user to a .cshtml page to enter their username and password. Thanks.

By Michael Washington on   1/29/2020 4:39 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

Hi,
One simple thing, how do I get the error msg from .cshtml back to loginControl.razor?
I want to display when wrong credentials were entered.
Thanks for the tutorial.

By fjd on   2/7/2020 4:22 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@fjd - Sorry I don't have an example.

By Michael Washington on   2/7/2020 4:23 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

Hi,
my .AspNetCore.Cookie is writed but LoginControl.razor show only the NotAuthorized node..

By simone on   2/17/2020 10:07 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@simone - Please download the sample provided on the Downloads page of this site and compare the code to your own.

By Michael Washington on   2/17/2020 10:08 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

Hi, any idea why login block isn't visible on mobile devices?

By ARtur on   3/5/2020 4:51 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@ARtur - A login button needs to be added to the mobile menu. See: https://github.com/ADefWebserver/Blazor-Blogs/blob/master/BlazorBlogs/Shared/NavMenu.razor

By Michael Washington on   3/5/2020 4:53 AM
Gravatar

Why there is: services.AddScoped<HttpContextAccessor>();

services.AddHttpContextAccessor(); //adds singleton IHttpContextAccessor (https://source.dot.net/#Microsoft.AspNetCore.Http/HttpServiceCollectionExtensions.cs,311e627947384f0b), which is as I understand it, is used everywhere in the code.

I see that the code is based on https://github.com/aspnet/Blazor/issues/1554, but I am not able to find any reason for adding the scoped instance when there is already a singleton one. I have tried to remove the scoped instance in my code (based on your sample) and it seems to work without any problem.

By IvanH on   3/6/2020 4:58 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

@IvanH - This sample has evolved over several versions of Blazor. The line was needed at one point, but, may no longer be required for this sample. However, there are other samples that build on this sample, so I have kept it in because it does not cause any problems.

By Michael Washington on   3/6/2020 5:00 AM
Gravatar

Re: A Demonstration of Simple Server-side Blazor Cookie Authentication

Hello Michael,

Unfortunately using a get request is not secure because browsers like firefox remembers the user name and password in the url ! What I ended doing is I encrypted the username and current time tick to generate a unique url, that I decrypt on the login.cshtml.cs, as my application requirements can’t use a separate login page.

Regards,

Raphaël

By Raphaël Desalbres on   5/5/2020 4:33 AM
Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation