IConfiguration vs IOptions NET
Synchronous and Asynchronous in .NET Core
Model Binding and Validation in ASP.NET Core
ControllerBase vs Controller in ASP.NET Core
ConfigureServices and Configure methods
IHostedService interface in .NET Core
ASP.NET Core request processing
| Build taxi-booking application :👈 | 👉:Service Per Subdomain Pattern |
Tenant ID |
A Tenant ID is a globally unique identifier (GUID) that represents an organization (tenant) in a cloud identity system such as Microsoft Entra ID (formerly Azure Active Directory).
Think of it as:
Country -> State -> City -> Tenant -> Users
or
Microsoft Cloud
|
+---- Tenant A (Company A)
|
+---- Tenant B (Company B)
|
+---- Tenant C (Company C)
Each tenant receives a unique Tenant ID.
Example:
Tenant Name: Contoso Ltd Tenant ID: 72f988bf-86f1-41af-91ab-2d7cd011db47
A tenant is an isolated container that stores:
Users Groups Applications Roles Permissions Policies Licenses Devices
Example:
Microsoft Entra ID
Tenant A
Users:
John
David
Admin
Tenant B
Users:
Alice
Bob
Tenant C
Users:
Smith
Data is isolated between tenants.
Without Tenant IDs:
John from Company A John from Company B How does Microsoft know which company?
Using Tenant IDs:
Tenant A
John
Tenant B
John
The Tenant ID uniquely identifies the organization.
A Tenant ID is always a GUID.
Example:
f8cdef31-a31e-4b4a-93e4-5f571e91255a
Length:
36 characters
Pattern:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
When users log in:
User Login
|
v
Tenant ID
|
v
Find Organization
|
v
Authenticate User
Example:
Taxi Booking Admin Portal
Application belongs to:
Tenant: Contoso Tenant ID:72f988bf-86f1-41af-91ab-2d7cd011db47
When calling APIs:
GET api/bookings Authorization: Bearer Token
Token contains:
{
"tid": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
tid = Tenant ID
Example:
SaaS CRM Application
Customers:
TCS Infosys Wipro Accenture
Each customer gets:
Different Tenant ID
Used to separate data.
Many developers confuse these.
Represents:
Identity Organization
Contains:
Users Groups Applications
Example:
72f988bf-86f1-41af-91ab-2d7cd011db47
Represents:
Billing Account
Contains:
VMs Databases Storage
Example:
b9dc1c45-df2a-48a1-8f4b-5d8f462b9ab7
Relationship:
Tenant
|
+------- Subscription 1
|
+------- Subscription 2
|
+------- Subscription 3
One tenant can have multiple subscriptions.
Another common confusion.
Organization
Example:
Contoso
Application
Example:
Taxi Booking Portal
Diagram:
Tenant
|
+---- Application A
| Client ID
|
+---- Application B
| Client ID
|
+---- Application C
Client ID
Only one organization can use it.
Contoso Only
Authentication URL:
https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Example:
https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2/v2.0/token
Many organizations can use it.
Example:
Salesforce GitHub Enterprise ServiceNow
Flow:
Company A
Company B
Company C
|
v
Multi-Tenant App
When authentication succeeds:
{
"aud": "api://taxi-app",
"iss": "https://login.microsoftonline.com/",
"tid": "72f988bf-86f1-41af-91ab-2d7cd011db47",
"sub": "123456789",
"name": "John Doe"
}
Useful for:
Authorization User Isolation Data Segregation Auditing
Suppose you build:
Taxi Fleet Management Platform
Customers:
Uber Fleet Ola Fleet Rapido Fleet
Database:
Companies --------- CompanyId TenantId Name Bookings --------- BookingId TenantId CustomerId
Every query uses:
WHERE TenantId = @TenantId
This prevents customers from seeing each other's data.
Azure Portal → Microsoft Entra ID → Overview → Tenant ID
Example:
Directory (Tenant) ID: 72f988bf-86f1-41af-91ab-2d7cd011db47
az account show
Result:
{
"tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
Get-AzTenant
Used for:
Reading the Tenant ID from a JWT token in an ASP.NET Core API:
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
[ApiController]
[Route("api/[controller]")]
public class BookingController : ControllerBase
{
[HttpGet]
public IActionResult GetBookings()
{
string tenantId = User.FindFirst("tid")?.Value;
return Ok(new
{
Message = "Tenant identified successfully",
TenantId = tenantId
});
}
} Example JWT:
{
"tid": "72f988bf-86f1-41af-91ab-2d7cd011db47",
"name": "John Doe"
}
Output:
{
"message": "Tenant identified successfully",
"tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47"
}
var tenantId = User.FindFirst("tid")?.Value;
var bookings = await _dbContext.Bookings
.Where(x => x.TenantId == tenantId)
.ToListAsync();
This ensures that users only access data belonging to their own organization, which is the primary purpose of a Tenant ID in multi-tenant cloud applications.
| Build taxi-booking application :👈 | 👉:Service Per Subdomain Pattern |