locked
Authenticate Blazor WebAssembly using multiple identity providers RRS feed

  • Question

  • User127869263 posted

    I am learning Blazor WebAssembly and building a small project to be hosted as Static Web App in Azure.

    The target framework is net5.0.

    When the user clicks over 'login' hyperlink or button, a new page will display the names of some identity providers (Microsoft, Google, SackOverflow, etc.). Then the user will select one to log in.

    I did it using just one identity provider (just Microsoft, just Google, etc.).

    How can I use multiple identity providers in the same app ?

    Someone can help me, please ?

    Some detais:
      Blazor WebAssembly App
      TargetFramework: net5.0
      Hosted as Static Web App in Azure 

    Program.cs

    using Blazored.LocalStorage;

    using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;

    using System;
    using System.Net.Http;
    using System.Threading.Tasks;

    namespace FileProcApp
    {
        public class Program
        {
            public static async Task Main(string[] args) {
                var builder = WebAssemblyHostBuilder.CreateDefault(args);
                builder.RootComponents.Add<App>("#app");

                builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

                builder.Services.AddOidcAuthentication(options => {
                    options.ProviderOptions.DefaultScopes.Clear();
                    options.ProviderOptions.DefaultScopes.Add("openid");
                    options.ProviderOptions.DefaultScopes.Add("offline_access");
                    builder.Configuration.Bind("AzureAd", options.ProviderOptions);
                });
                
                builder.Services.AddOidcAuthentication(options => {
                    options.ProviderOptions.DefaultScopes.Clear();               
                    builder.Configuration.Bind("Google", options.ProviderOptions);
                });


                builder.Services.AddBlazoredLocalStorage();

                builder.Services.AddSingleton<Services.Authentication>();

                await builder.Build().RunAsync();
            }
        }
    }

    appsettings.json

    {
      "Google": {
        "Authority": "https://accounts.google.com/",
        "ClientId": "1234567890123-45678901234567890123456789012345.apps.googleusercontent.com",
        "PostLogoutRedirectUri": "https://lorem-ipsun-dolor-sit-amet.azurestaticapps.net/authentication/logout-callback",
        "RedirectUri": "https://lorem-ipsun-dolor-sit-amet.azurestaticapps.net/authentication/login-callback",
        "ResponseType": "token id_token"
      },
      "AzureAd": {
        "Authority": "https://login.microsoftonline.com/common",
        "ClientId": "12345678-9012-3456-7890-123456789012",
        "ValidateAuthority": true
      }
    }

    LoginDisplay.razor

    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.WebAssembly.Authentication

    @using Microsoft.Extensions.Logging
    @using System.Text.Json

    @inject NavigationManager Navigation
    @inject SignOutSessionStateManager SignOutManager

    @inject Services.Authentication UserAuthentication

    @inject Blazored.LocalStorage.ILocalStorageService localStorage

    <AuthorizeView>
        <Authorized>
            Hello, @context.User.Identity.Name!

            <img src="img/UsrTeste.jpg" style="width:28px; cursor:pointer; " />
            <span style="cursor:pointer; ">usuario.teste@teste.com.br</span>

            <div>
                @System.Text.Json.JsonSerializer.Serialize(context.User.Identity, new JsonSerializerOptions() { WriteIndented = true });
                @RegistraAutenticacao();
            </div>
            <button class="nav-link btn btn-link" @onclick="BeginSignOut">Log out</button>
        </Authorized>
        <NotAuthorized>
            <a class="sign-in" href="authentication/register">Register</a>
            <a href="authentication/login">Log in</a>
        </NotAuthorized>
        <Authorizing>
            <span>Autorizando</span>
        </Authorizing>
    </AuthorizeView>


    @code{
        private async Task BeginSignOut(MouseEventArgs args)
        {
            await SignOutManager.SetSignOutState();
            Navigation.NavigateTo("authentication/logout");
        }
        private async Task RegistraAutenticacao() {
            Console.WriteLine("[LoginDisplay.razor.RegistraAutenticacao] Entrou");
            await UserAuthentication.RegistraAutenticacao();
            Console.WriteLine("[LoginDisplay.razor.RegistraAutenticacao] Saiu");
        }
    }

    Monday, March 29, 2021 6:06 PM

All replies

  • User1686398519 posted

    Hi AmauriRodrigues, 

    How can I use multiple identity providers in the same app ?

    In Blazor WebAssembly apps, authentication checks can be bypassed because all client-side code can be modified by users.

    You can add multiple authentication providers on the server side to log in.

    • In short, you can request the server to get the login page on the client (Blazor WebAssembly), which has multiple authentication provider buttons.

    Below are some links, you can refer to them.

    1. ASP.NET Core Blazor WebAssembly additional security scenarios
    2. Customize the authentication user interface
    3. You can search the following keywords to find some detailed examples:
      1. Facebook Authentication in Blazor WebAssembly Hosted Applications
      2. Google Authentication in Blazor WebAssembly Hosted Applications

    Best Regards,

    YihuiSun

    Wednesday, March 31, 2021 9:39 AM
  • User127869263 posted

    Hi YihuiSun,

    Thank You for your help.

    I need some way to identify and authenticate the user, without forcing to create new "user id" and "password", using identity providers (Microsoft, Google, SackOverflow, etc.).  

    That app will be hosted as Static Web App in Azure.  No server module.

    Some actions will post data to another module, hosted as Function App under Azure.  At that moment I have to know who is posting.

    I think that architecture  will be low cost (some processing in the client, and some processing in the Function App).

    I do know that authentication checks can be bypassed. However, regular users can not modify client-side code. 

    Is there a way to use multiple identity providers in this client-side application?

    Best Regards,

    Amauri Rodrigues

    Wednesday, March 31, 2021 8:32 PM