Categories
ASP.NET CORE Azure Blazor

Blazor WASM Call WebAPI Without Access Token

This is for Blazor WASM RC.

So imagine you have a Blazor WASM app, which is a SPA that user might need to sign in to perform some tasks via Web API. Take the case using Azure AD B2C, once we logged in, we’ll have ID and Access Token from Implicit Flow.

By default, the AADB2C template generates the following:

        builder.Services.AddHttpClient("HostedB2C.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
            .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
        // Supply HttpClient instances that include access tokens when making requests to the server project
        builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("HostedB2C.ServerAPI"));

This makes all WebAPIs with Access Token, refresh and such, which is great, secure and convenient.

However, what if there’s a need to call WebAPI as anonymous user?

As of now, there’s no official documentation (should be coming soon). Basically, we can add multiple AddHttpClient for the use case without auth.

To see this in action. In Program.cs, add

        builder.Services.AddHttpClient("HostedB2C.ServerAPI.NoAuth",
                client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

In the razor component:

@inject IHttpClientFactory ClientFactory

        var client = ClientFactory.CreateClient("HostedB2C.ServerAPI.NoAuth");
        forecasts = await client.GetFromJsonAsync<WeatherForecast[]>("WeatherForecastNA");

There! Now we can call WebAPI using alternative HttpClient (the one without auth).

Categories
ASP.NET CORE Azure Blazor

Tutorial: Azure ADB2C with Blazor

This series is specifically for Azure ADB2C with Blazor.

What is Azure ADB2C?

Azure Active Directory B2C provides business-to-customer identity as a service. Your customers use their preferred social, enterprise, or local account identities to get single sign-on access to your applications and APIs.

Infographic of Azure AD B2C identity providers and downstream applications

Azure Active Directory B2C (Azure AD B2C) is a customer identity access management (CIAM) solution capable of supporting millions of users and billions of authentications per day. It takes care of the scaling and safety of the authentication platform, monitoring and automatically handling threats like denial-of-service, password spray, or brute force attacks.

Why Do I need it?

Well, ASP.NET Core has Identity and it works outside the box. With some hacking, you can get it working on mobile apps as well. You can also use IdentityServer4 as your custom identity server that serves additional functionalities as well as offloading resources. But, what if there’s a solution that can address scaling and safety with reasonable good customization and ease of use? That’s what I think Azure AD B2C provides.

Additional benefit: It’s a free service as long the monthly active users is less than 50k.

There’s a lot of documentation on Azure AD B2C. However, they might be outdated and not target specifically for Blazor. Hence, this series aims to help bridge all the gaps.

At high level, the documentations are here:

Microsoft Azure Ad B2C documentation

For WASM:

For Server side, it works right outside the template. The trick is to get access token

That should be it! You should be able to get ID Token and Access Token. You can protect your APIs and validate that Access Token does grant access.

Enjoy the long read… but once you understand how this works, it will save you tons of time in the future develop identity solutions.

Categories
ASP.NET CORE Azure Blazor

Get Access Token from Azure ADB2C for Blazor Server Side

This is part of the series for AAD B2C with Blazor. This post is for Blazor Server Side.

Blazor Server Side is released with default template support for AADB2C. It works great except there’s NO DOCUMENTATION on how to get Access Token.

Luckily, you ran to this post. I’ve gone through it with MSFT engineers and here’s how to hack up a sample. Many thanks to Luke Latham and Javier Calvarro Nelson.

So let’s get down to the code.

First of all, download the sample https://github.com/javiercn/blazor-server-aad-sample

This sample is for AAD and not for AADB2C, so some customizations are needed:

services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme).AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options));

Scope need to add:

options.Scope.Add("https://{domain}.onmicrosoft.com/api/demo.read");

//Change response to
changed the options.ResponseType = “code id_token”;

I left out resource since I have no idea what’s that from documentation nor code.

I was able to get the access token.

One side note. His sample code have options.Scope.Add(“offline_access”);

I made the mistake of thinking I only need to add “demo.read” instead of the whole path. Adding the whole path solved my issue. Again, this is not documented? I just happen to read some code that doesn’t work on SO who had this line somewhere.

That’s about it! You can replace Identity with this great service from Azure!

Categories
ASP.NET CORE Azure Blazor

Blazor AAD B2C Additional user flows

This is part of Blazor AAD B2C Series. This post is on Blazor WASM.

Microsoft introduced AADB2C support in Blazor 3.2 Preview: Link

Once followed through my troubleshoot blog, you should be able to get authentication setup. However, what about edit profile and reset password user flow? There’s absolutely NO DOCUMENTATION ON THIS!

Luckily I’ve gone through the process and here’s an example of how to get it to work. Let’s get on with it

  • Registered a callback in the portal for a password reset: https://localhost:5001/passwordreset-callback
  • Have a basic password reset user flow: B2C_1_passwordreset1

In LoginDisplay, Hack up a challenge …

<button class="nav-link btn btn-link" @onclick="ResetPassword">Reset password</button>

...

private void ResetPassword(MouseEventArgs args)
{
    Navigation.NavigateTo("https://XXXXX.b2clogin.com/XXXXX.onmicrosoft.com/oauth2/v2.0/authorize?" +
        "client_id=11111111-1111-1111-1111-111111111111" +
        "&redirect_uri=https%3A%2F%2Flocalhost%3A5001%2Fpasswordreset-callback" +
        "&response_mode=query" +
        "&response_type=id_token" +
        "&scope=openid" +
        $"&nonce={Guid.NewGuid()}" +
        "&state=12345" +
        "&p=B2C_1_passwordreset1");
}

A component to handle the callback (PasswordReset.razor) …

@page "/passwordreset-callback"
@inject NavigationManager Navigation

<p>@_errorMessage</p>
<p>@_errorDescription</p>

@code {
    private string _errorMessage;
    private string _errorDescription;

    protected override void OnInitialized()
    {
        var state = QueryStringHelper.GetParameter(new Uri(Navigation.Uri).Query, "state");

        if (state == "12345")
        {
            var error = QueryStringHelper.GetParameter(new Uri(Navigation.Uri).Query, "error");

            if (error == "")
            {
                Navigation.NavigateTo("/");
            }

            _errorMessage = $"Error: {error}";

            _errorDescription = $"Description: {QueryStringHelper.GetParameter(new Uri(Navigation.Uri).Query, "error_description")}";
        }
    }
}

Use the QueryStringHelper from the repo at https://github.com/dotnet/aspnetcore/blob/blazor-wasm/src/Components/WebAssembly/WebAssembly.Authentication/src/QueryStringHelper.cs.

And… drumroll… it just works.

Categories
ASP.NET CORE Azure Blazor

TROUBLESHOOT: ASP.NET Core Blazor WebAssembly hosted app with Azure Active Directory B2C

In Blazor WASM 3.2.0 Preview 2, Microsoft announced support for Token-based authentication. In particular, IdentityServer, OpenID Connect provider, and Azure Active Directory B2C.

THIS ARTICLE IS SPECIFICALLY FOR AZURE ACTIVE DIRECTORY B2C

Follow the guide: https://docs.microsoft.com/en-us/aspnet/core/security/blazor/webassembly/hosted-with-azure-active-directory-b2c?view=aspnetcore-3.1#create-the-app

We should be able to create an app that’s able to use AAD B2C for login and use API securely.

In creating the app, it requires carefully crafted command to create the app: dotnet new blazorwasm -au IndividualB2C –aad-b2c-instance “{AAD B2C INSTANCE}” –api-client-id “{SERVER API APP CLIENT ID}” –app-id-uri “{APP ID URI}” –client-id “{CLIENT APP CLIENT ID}” –default-scope “{DEFAULT SCOPE}” –domain “{DOMAIN}” -ho -ssp “{SIGN UP OR SIGN IN POLICY}” –tenant-id “{TENANT ID}”

I tried this several times and I keeps on getting weird issues.

  1. On Chrome, I’ll get some weird PERMISSION issue. It works on Firefox and Edge, so this is probably not something I did wrong. Most likely will get fixed in the future.
  2. After Login, LoginDisplay gets my displayname correctly, however, when visit FetchData, the app will crash due to token been null

For 2, after hours, seems create app generation might cause an issue in builder.Services.AddMsalAuthentication.

Incorrect Generated: options.ProviderOptions.DefaultAccessTokenScopes.Add(“https:// XXXXXX.onmicrosoft.com/https:// XXXXXX.onmicrosoft.com/11111111-1111-1111-1111-111111111111/API.Access”);

Working solution:

options.ProviderOptions.DefaultAccessTokenScopes.Add(“https://XXXXXX.onmicrosoft.com/11111111-1111-1111-1111-111111111111/API.Access”);

Hopefully this helps someone else.

Categories
ASP.NET CORE Azure Razor Pages

How to Use SQLite on ASP.NET Core Project and Host on Azure

Often time, we just want to experiment some ideas. Just have a basic database setup on Azure will have some cost.

High Level Cost Options:

Min CostProsCons
SQL Server/Database>$0Full Feature ProductionNot Free
MySQL/Database >$0Full Feature Production Not Free
MySQL Preview/Database $0FreeNot scalable, Storage Size on Server
SQLite/Database $0Free, smallNot production

What if we just want to keep the cost down? Furthermore, if the idea really works, we can have easy way to migrate to SQL Server. Well, this post is for you.

NOTE: DO NOT USE SQLITE on PRODUCTION!

Prerequisite: Let’s assume you created the project with Authentication option selected. This will have Application DB Context setup, as well as Startup.cs will have services.AddDbContext. Let’s start.

Port SQLite

Step 1: Add SQLite support. In {your project}.csproj, add

<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.1" />

Note: At the time of writing, I am using version 3.1.1

Step 2: Add DefaultSQLiteConnection connection string. In appsettings.json, add a DefaultSQLiteConnection

  "ConnectionStrings": {
    "DefaultConnection": "omitted", 
    "DefaultSQLiteConnection": "Data Source=appdb.sqlite"
  },

Step 3: Modify Startup.cs

Remove

services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(                  Configuration.GetConnectionString("DefaultConnection")));

Add

    services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultSQLiteConnection")));

Step 4: Migration. Delete \Migrations folder. Open Package Manager Console (Tools->Nuget Package Manager -> Package Manager Console).

add-migration initSQLite
update-database

That’s it! Run and test. You should see appdb.sqlite being created at the project root.

Troubleshoot: If something went wrong, check csproj file and make sure Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Tools are there.

DEPLOY SQLite on Azure

I had lots of trouble hosting on azure mainly due to lack of documentation. The key is to have the correct db connection string and export the sqlite db to Azure.

  1. Connection String: In Azure portal, Settings -> Configurations -> Application Settings -> Connection String. The Name is what you selected (using the example above, it would be “DefaultSQLiteConnection”. The Value is: Data Source=D:\home\site\wwwroot\App_Data\appdb.sqlite. The Type is: “Custom”
  2. For the actual db. Since we cannot migrate, we have to ftp it. We can use Kudu tool: https://{your project}.scm.azurewebsites.net . Then navigate to Debug Console -> PowerShell. Go to D:\home\site\wwwroot\ and create App_Data folder. There you can drag and drop your sqlite db. Your app should work now

Troubleshoot: If it doesn’t work and you’ve tried 100 times. You keep getting 500.30. Just delete the app and recreate it. I have spent hours and yet to figure out what’s the issue.

Caveat on using SQLite and EF Core. Migration deployment doesn’t work. Migration doesn’t even work locally. So migrate the database (I just delete migration folder and reinit). Then, I copy the new db to Azure.

Categories
ASP.NET CORE Azure Blazor Products Razor Pages

2020 Web Dev Learning Essentials

Below demonstrates the necessary knowledge required to become a reasonable Web Developer at 2020. This is tailored for .NET Developer.

Will update this into flow charts in the near future.

Categories
ASP.NET CORE Azure Products

Prerequisites

Part III of the Series Web Development for Experienced (Non-Web) Software Engineers

This post outlines the tools and services required for the series. Bold is Recommended for this series. I’ll write more later to elaborate some of the choices.

Wow, that’s a lot of downloads just to get started using one platform. Imagine how much more will need to download and update if we use different tech stack.

Categories
ASP.NET CORE Azure Blazor Products Razor Pages

Scope

Part II of the Series Web Development for Experienced (Non-Web) Software Engineers

This series is for experienced engineers who wants to understand more about web development. Here we’ll try to cover as much as possible while being cost conscious. Most importantly, still use the best tools and services that can be used in a professional and production environment.

We will cover from tools and services required. Simple architectures. Tutorials. Customization. Development Process. And actual deployment (and service customization).

We are going to be using Microsoft ASP.NET CORE and Azure as our stack. Having everything together that just works is great.

Let’s get started.