What are we building?
The goal of this post is to create a simple ASP.NET Core Hosted Blazor WebAssembly website with an authentication mechanism using Okta as the identity provider. Since WebAssembly is a single-page application (SPA), we will be using the proof key for code exchange (PKCE, pronounced “pixy”) authentication flow which helps mitigate problems with authorization code interception in public clients (e.g., web browsers).
Requirements
- You have a beginners level knowledge of Blazor WebAssembly
- You are using Visual Studio 2022
- You have free Okta developer account (https://developer.okta.com/signup/)
Step 1: Create the project in Visual Studio
Open Visual Studio 2022 and select new Blazor WebAssembly App project.
Name your project anything you want.
I am going to use “BlazorWasmHosted4Blog” for this example.
On the Additional Information dialog, select the following:
- Authentication Type: Individual Accounts
NOTE: we are not going to setup a user database, but we will use the default routing to provide the authentication callback controllers - Configure for HTTPS
- APS.NET Core Hosted option
Step 2: Modify BlazorWasmHosted4Blog.Server
Add Okta.AspNetCore NuGet package
From the Package Manager prompt, type:Install-Package Okta.AspNetCore -ProjectName BlazorWasmHosted4Blog.Server
or, use the Nuget Package Manager:
Open Properties/launchsettings.json
Make note of the URL value your application is using for HTTPS. In this example, if we are debugging from IISExpress, the application URL will be https:// localhost:44365. If we are debugging from Kestrel, then the Application URL will be https:// localhost:7198. This URL value will be used shortly in the Okta app integration configuration.
Edit Program.cs in the *.Server project
Comment out the DBContext, IdentityServer and JWT Authentication services (don’t delete these lines, we might use these in an upcoming post). This code was added by default because we chose the Individual Accounts authentication type, but we will not be using it for now.
Next, add the Okta/OIDC service to the DI container. This code will direct the authentication manager to use Okta as the default identity provider.
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
})
.AddOktaWebApi(new OktaWebApiOptions()
{
OktaDomain = builder.Configuration["Okta:OktaDomain"]
});
Also, comment out the line “app.UseIdentityServer();” as we are using Okta instead.
Notice the Configuration key “Okta:OktaDomain” in the code above. Currently that does not exist, so we will add that to the *.Server appsetting.json file. But first, let’s configure the Okta app integration.
Step 3: Logon to your Okta developer account
Create App Integration
Select “Applications->Applications” in the sidebar menu, and select “Create App Integration.”
Choose Sign-in method: OIDC – OpenID Connect.
Choose Application type: Single-Page Application, and click Next.
Choose a name for this app integration and ensure Grant type: Authorization Code is checked.
Using the Port we copied from the project’s launchSettings.json, replace the Sign-in and Sign-out redirect URLs with:
https://localhost:{PORT}/authentication/login-callback
and
https://localhost:{PORT}/authentication/logout-callback
This utilizes the callbacks setup by ASP.NET Core Identity.
For now we will leave everything else as their defaults and allow everyone in the organization access to this application.
Copy the Client Credentials and Okta Domain
We will use these in the project appsetting.json. Notice that a Client Secret is not included in the app integration configuration. PKCE is the default for SPA applications on Okta. If you decide to use another OIDC identity provider, make sure this is selected.
Step 4: Return to the BlazorWasmHosted2.Server project
Edit appsettings.json
Now we are going to use the configuration from above to set the Okta:OktaDomain value in the Server project.
"Okta": {
"OktaDomain": "{OKTAURL}"
},
Edit _LoginPartial.cshtml
_LoginPartial.cshtml is located in the .Server project under Areas->Identity->Pages->Shared. Locate the line:@if (SignInManager.IsSignedIn(User))
and change it to:@if (User is not null)
For now we are going to assume if the user object has been initialized, then we are dealing with an authorized user. This is not production-ready. You will want to verify claims from the identity provider, but that is outside the scope of this post.
Step 5: Open the BlazorWasmHosted2.Client project
Add and edit appsettings.json
By default the Client project will not have an appsettings file, so add new JSON file in the wwwroot folder and name it “appsettings.json”. Replace the default content with the Okta app configuration values.
{
"Okta": {
"Authority": "https://{OKTAURL}/oauth2/default",
"ClientId": "CLIENTID"
}
}
Edit Program.cs in the *.Client project
Add the following code before “builder.Services.AddApiAuthorization();” to provider values to the authenticating service.
builder.Services.AddOidcAuthentication(options =>
{
options.ProviderOptions.Authority = builder.Configuration.GetValue<string>("Okta:Authority");
options.ProviderOptions.ClientId = builder.Configuration.GetValue<string>("Okta:ClientId");
options.ProviderOptions.ResponseType = "code";
});
Step 6: Run BlazorWasmHosted2.Server
Click “Log in”
The application redirects to the Okta app Sign-in page. Submit your developer account login information.
Now the application is redirected back to your Blazor app, and you are authenticated!
This is your first step in securing your Blazor WebAssembly website with Okta. What should you do next?