Welcome to Blogs Overflow: Empowering Knowledge by Overflow Orbits Private Limited.- Azure B2C SSO Implementation with Angular 16 and .NET Core 6. I will provide a structured code for a demo application implementing Azure B2C SSO with Angular 16 and .NET Core 6. Below are the steps and the necessary code examples.
Step-by-Step Guide
1. Create Angular Application
1.1: Initialize Angular Project
ng new azure-b2c-angular-demo --routing --style=css
cd azure-b2c-angular-demo
1.2: Install Dependencies
npm install @azure/msal-browser @azure/msal-angular
npm install @angular/material @angular/cdk
ng add @angular/material
1.3: Create auth-config.ts
in src/app
export const b2cPolicies = {
names: {
signUpSignIn: "b2c_1_susi",
},
authorities: {
signUpSignIn: {
authority: "https://<your-tenant>.b2clogin.com/<your-tenant>.onmicrosoft.com/b2c_1_susi",
},
},
};
export const msalConfig = {
auth: {
clientId: "<your-client-id>",
authority: b2cPolicies.authorities.signUpSignIn.authority,
redirectUri: "http://localhost:4200",
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: false,
},
};
export const loginRequest = {
scopes: ["openid", "profile"],
};
1.4: Configure MSAL in app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { MsalModule, MsalService, MsalGuard, MsalBroadcastService } from '@azure/msal-angular';
import { msalConfig, loginRequest } from './auth-config';
import { InteractionType } from '@azure/msal-browser';
import { ProfileComponent } from './profile/profile.component';
import { HomeComponent } from './home/home.component';
const routes: Routes = [
{ path: 'profile', component: ProfileComponent, canActivate: [MsalGuard] },
{ path: '', component: HomeComponent },
];
@NgModule({
declarations: [AppComponent, ProfileComponent, HomeComponent],
imports: [
BrowserModule,
RouterModule.forRoot(routes),
MsalModule.forRoot(msalConfig, {
interactionType: InteractionType.Redirect,
authRequest: loginRequest,
}),
],
providers: [MsalService, MsalGuard, MsalBroadcastService],
bootstrap: [AppComponent],
})
export class AppModule {}
1.5: Implement Sign-In and Sign-Out in app.component.ts
import { Component, OnInit } from '@angular/core';
import { MsalService } from '@azure/msal-angular';
@Component({
selector: 'app-root',
template: `
<button *ngIf="!isLoggedIn" (click)="login()">Login</button>
<button *ngIf="isLoggedIn" (click)="logout()">Logout</button>
<router-outlet></router-outlet>
`,
})
export class AppComponent implements OnInit {
isLoggedIn = false;
constructor(private authService: MsalService) {}
ngOnInit() {
this.authService.instance.handleRedirectPromise().then((res) => {
if (res && res.account) {
this.authService.instance.setActiveAccount(res.account);
}
this.isLoggedIn = !!this.authService.instance.getActiveAccount();
});
}
login() {
this.authService.loginRedirect();
}
logout() {
this.authService.logoutRedirect();
}
}
1.6: Create Profile Component in src/app/profile/profile.component.ts
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../api.service';
@Component({
selector: 'app-profile',
template: `
<div *ngIf="weatherData">
<h2>Weather Forecast</h2>
<ul>
<li *ngFor="let item of weatherData">{{ item.date }}: {{ item.temperatureC }}°C, {{ item.summary }}</li>
</ul>
</div>
`,
})
export class ProfileComponent implements OnInit {
weatherData: any;
constructor(private apiService: ApiService) {}
ngOnInit() {
this.apiService.getWeatherForecast().subscribe((data) => {
this.weatherData = data;
});
}
}
1.7: Create API Service in src/app/api.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { MsalService } from '@azure/msal-angular';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient, private authService: MsalService) {}
getWeatherForecast(): Observable<any> {
const account = this.authService.instance.getActiveAccount();
const headers = account ? {
Authorization: `Bearer ${account.idToken}`
} : {};
return this.http.get('https://localhost:5001/weatherforecast', { headers });
}
}
2. Create .NET Core 6 API Project
2.1: Initialize API Project
dotnet new webapi -n AzureB2CApi
cd AzureB2CApi
2.2: Install JWT Middleware
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
2.3: Configure JWT Authentication in Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://<your-tenant>.b2clogin.com/<your-tenant>.onmicrosoft.com";
options.Audience = "<your-client-id>";
});
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
2.4: Secure API Endpoints in Controllers/WeatherForecastController.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace AzureB2CApi.Controllers
{
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}
3. Repository Structure
Here is the structure of the repository:
azure-b2c-demo/
├── azure-b2c-angular-demo/
│ ├── src/
│ │ ├── app/
│ │ │ ├── auth-config.ts
│ │ │ ├── api.service.ts
│ │ │ ├── profile/
│ │ │ │ ├── profile.component.ts
│ │ │ ├── home/
│ │ │ │ ├── home.component.ts
│ │ │ ├── app.module.ts
│ │ │ ├── app.component.ts
│ │ ├── main.ts
│ ├── angular.json
│ ├── package.json
├── AzureB2CApi/
│ ├── Controllers/
│ │ ├── WeatherForecastController.cs
│ ├── Program.cs
│ ├── AzureB2CApi.csproj
azure-b2c-demo/
├── azure-b2c-angular-demo/
│ ├── src/
│ │ ├── app/
│ │ │ ├── profile/
│ │ │ │ ├── profile.component.html
│ │ │ │ ├── profile.component.ts
│ │ │ ├── home/
│ │ │ │ ├── home.component.html
│ │ │ │ ├── home.component.ts
│ │ │ ├── auth-config.ts
│ │ │ ├── api.service.ts
│ │ │ ├── app.module.ts
│ │ │ ├── app.component.html
│ │ │ ├── app.component.ts
│ │ ├── main.ts
│ ├── angular.json
│ ├── package.json
│ ├── tsconfig.json
├── AzureB2CApi/
│ ├── Controllers/
│ │ ├── WeatherForecastController.cs
│ ├── Properties/
│ │ ├── launchSettings.json
│ ├── appsettings.json
│ ├── Program.cs
│ ├── AzureB2CApi.csproj
│ ├── WeatherForecast.cs
├── README.md
GitHub Repository Setup – Azure B2C SSO Implementation with Angular 16 and .NET Core 6
- Initialize Git:
git init
- Add Files:
git add .
- Commit Changes:
git commit -m "Initial commit with Azure B2C SSO in Angular and .NET Core"
- Add Remote Repository:
git remote add origin <your-git-repo-url>
- Push Changes:
bash git push -u origin master