Where are MicrosoftIdentity Area, AccountController, and Action?
The MicrosoftIdentity area and Account controller are part of the Microsoft Identity Web library, which provides integration with Azure AD and Azure AD B2C for ASP.NET Core applications. This library simplifies the process of adding authentication and authorization to your application.
Microsoft Identity Web Library
The Microsoft Identity Web library includes built-in controllers and views for handling common authentication tasks, such as signing in, signing out, and editing user profiles. These are organized within the MicrosoftIdentity area.
Key Components
- MicrosoftIdentity Area:
- The
MicrosoftIdentityarea contains the built-in controllers and views provided by the Microsoft Identity Web library. - This area is automatically registered and used by the library to handle authentication-related actions.
- The
- Account Controller:
- The
Accountcontroller within theMicrosoftIdentityarea handles actions such as signing in, signing out, and editing user profiles. - These actions correspond to the methods provided by the Microsoft Identity Web library to manage user authentication and profile management.
- The
Example of Built-In Actions
- SignIn: Initiates the sign-in process.
- SignOut: Initiates the sign-out process.
- EditProfile: Initiates the profile editing process (if configured).
Example Usage in _LoginPartial.cshtml
In the _LoginPartial.cshtml file, you are using the asp-area, asp-controller, and asp-action attributes to link to the built-in actions provided by the Microsoft Identity Web library:
<ul class="navbar-nav">
@if (User.Identity?.IsAuthenticated == true)
{
@if (!string.IsNullOrEmpty(options.EditProfilePolicyId))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="EditProfile">Hello @User.Identity?.Name!</a>
</li>
}
else
{
<span class="navbar-text text-dark">Hello @User.Identity?.Name!</span>
}
<li class="nav-item">
<a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignOut">Sign out</a>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn">Sign in</a>
</li>
}
</ul>
How do each of the actions know where to go in AAD B2C to accomplish the tasks?
The actions in the _LoginPartial.cshtml file (SignIn, SignOut, and EditProfile) know where to go in Azure AD B2C to accomplish their tasks because they are configured through the Microsoft Identity Web library, which handles the integration with Azure AD B2C. The configuration in your Program.cs file and the settings in your appsettings.json or appsettings.Development.json file provide the necessary information for these actions to work correctly.
Configuration in Program.cs
In Program.cs file, you configure the authentication middleware to use Azure AD B2C:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
using System.IdentityModel.Tokens.Jwt;
var builder = WebApplication.CreateBuilder(args);
// This is required to be instantiated before the OpenIdConnectOptions starts getting configured.
// By default, the claims mapping will map claim names in the old format to accommodate older SAML applications.
// This flag ensures that the ClaimsIdentity claims collection will be built from the claims in the token
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
// The appsettings file containing AAD B2C endpoints for policy endpoints.
var azureAdB2CSection = builder.Configuration.GetSection("AzureAdB2C");
// Add services to the container. Here we are adding the MicrosoftIdentity middleware to have
// those actions for signing in, signing out, or editing the user profile.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(azureAdB2CSection)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
Configuration in appsettings.Development.json
appsettings.Development.json file contains the Azure AD B2C settings:
{
"AzureAdB2C": {
"Instance": "https://myapp.b2clogin.com",
"TenantId": "myapp.onmicrosoft.com",
"ClientId": "49000000-0000-0000-aaaa-cc8844bbdd33",
"Domain": "tenant.onmicrosoft.com",
"SignedOutCallbackPath": "/signout/B2C_1_susi",
"SignUpSignInPolicyId": "B2C_1_SignInSignUp",
"ResetPasswordPolicyId": "B2C_1_Reset",
"EditProfilePolicyId": "B2C_1_EditProfile",
"CallbackPath": "/signin-oidc"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
The actions in the _LoginPartial.cshtml file (SignIn, SignOut, and EditProfile) know where to go in Azure AD B2C to accomplish their tasks because they are configured through the Microsoft Identity Web library, which handles the integration with Azure AD B2C. The configuration in your Program.cs file and the settings in your appsettings.json or appsettings.Development.json file provide the necessary information for these actions to work correctly.
How Actions Know Where to Go
- SignIn:
- The
SignInaction uses theSignUpSignInPolicyIdfrom the configuration to initiate the sign-in process. - The Microsoft Identity Web library handles the redirection to the Azure AD B2C sign-in page using the specified policy.
- SignOut:
- The
SignOutaction uses theSignedOutCallbackPathfrom the configuration to handle the sign-out process. - The Microsoft Identity Web library handles the redirection to the Azure AD B2C sign-out page and then redirects back to the specified callback path.
- EditProfile:
- The
EditProfileaction uses theEditProfilePolicyIdfrom the configuration to initiate the profile editing process. - The Microsoft Identity Web library handles the redirection to the Azure AD B2C profile editing page using the specified policy.
Summary
The actions (SignIn, SignOut, and EditProfile) in the _LoginPartial.cshtml file know where to go in Azure AD B2C because they are configured through the Microsoft Identity Web library. The configuration in your Program.cs file and the settings in your appsettings.Development.json file provide the necessary information for these actions to work correctly. The Microsoft Identity Web library handles the redirection to the appropriate Azure AD B2C pages based on the specified policies.
Azure AD B2C: Custom Policies and User Journeys Explained
Overview: Azure AD B2C custom policies are like the rules that define how users log in and interact with your app. Think of them as the blueprint for creating a secure and personalized user experience.
Key Features:
- Customizable UI & User Journeys: Imagine customizing the login page to match your app’s theme and guiding users through specific steps based on their actions.
- Integration with External Providers: You can allow users to log in using their Google or Facebook accounts, making it super convenient.
- Claims & Business Logic: Claims are like temporary data storage (e.g., user’s name or email) used during the login process. You can transform these claims to fit your app’s needs.
Starter Pack Policies:
- LocalAccounts: Users log in with local accounts only.
- SocialAccounts: Users log in with social accounts only.
- SocialAndLocalAccounts: Users can choose between local and social accounts.
- SocialAndLocalAccountsWithMFA: Adds multifactor authentication for extra security.
Claims:
- Definition: Claims are like variables in programming, storing user info temporarily during login. They are stored in a claims bag during this process. Each step pulls claims out of the bag, uses / changes them, and puts them back in the bag for the next step.
- Usage:
- Saved, Read, Updated: E.g., updating user profile info.
- External Providers: E.g., Google or Facebook logins.
- User Interaction: Collected during sign-up/profile edit.
- Transformed: Modified before being included in the token.
Customizing UI:
- Use self-asserted technical profiles to collect user info.
- Technical profiles are interfaces created to communicate with different types of parties. All interactions where the user is expected to provide input are self-asserted technical profiles.
- Customize the UI with HTML content via content definition element.
- Localize strings using the localization element.
- Executes specific user journeys for relying party applications (service providers in SAML).
- Specifies user journey and claims in the token.
User Journeys & Orchestration Steps:
- User Journeys: Define the path users follow to access your app.
- Orchestration Steps: Steps to collect user info and present it to the app. Steps can be conditional based on preconditions.
Best Practices:
- Extension Policy: Create business logic here, not in the base policy.
- Technical Profile Inclusion: Reduce duplication by sharing core functionality.
- Avoid Directory Writes During Sign-In: Prevent throttling issues.
- High Availability: Ensure external dependencies (e.g., REST APIs) are highly available.
- Global Deployment: Use Azure CDN for custom HTML templates.
Troubleshooting:
- Use Application Insights to diagnose exceptions.
- Azure AD B2C extension for Visual Studio Code helps visualize logs.
- Use XML schema validation to identify errors.
Links:
DotNet File Locations in MacOS & Removing .Net
All Files: /usr/local/share/dotnet/
SDKs: /usr/share/dotnet/sdk/$version/
Runtime: /usr/share/dotnet/shared/$product/$version
.Net Host: /usr/share/dotnet/host/fxr/$version/
To remove a product: sudo rm -rf /usr/share/dotnet/<one-of-the-above-paths>
Example:
/usr/local/share/dotnet/sdk$ ls
7.0.400 7.0.403
/usr/local/share/dotnet/sdk$ sudo rm -rf 7.0.400
Password:
/usr/local/share/dotnet/sdk$ ls
7.0.403
/usr/local/share/dotnet/sdk$ cd ..
/usr/local/share/dotnet$ ls
LICENSE.txt host sdk-manifests
ThirdPartyNotices.txt packs shared
dotnet sdk templates
/usr/local/share/dotnet$ cd shared
/usr/local/share/dotnet/shared$ ls
Microsoft.AspNetCore.App Microsoft.NETCore.App
/usr/local/share/dotnet/shared$ cd Microsoft.AspNetCore.App
/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App$ ls
7.0.10 7.0.13
/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App$ sudo rm -rf 7.0.10
/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App$ cd ..
/usr/local/share/dotnet/shared$ cd Microsoft.NETCore.App
/usr/local/share/dotnet/shared/Microsoft.NETCore.App$ ls
7.0.10 7.0.13
/usr/local/share/dotnet/shared/Microsoft.NETCore.App$ sudo rm -rf 7.0.10
/usr/local/share/dotnet/shared/Microsoft.NETCore.App$ ls
7.0.13
/usr/local/share/dotnet/shared/Microsoft.NETCore.App$ cd ../..
/usr/local/share/dotnet$ ls
LICENSE.txt host sdk-manifests
ThirdPartyNotices.txt packs shared
dotnet sdk templates
/usr/local/share/dotnet$ cd host
/usr/local/share/dotnet/host$ ls
fxr
/usr/local/share/dotnet/host$ cd fxr
/usr/local/share/dotnet/host/fxr$ ls
7.0.10 7.0.13
/usr/local/share/dotnet/host/fxr$
/usr/local/share/dotnet/host/fxr$ sudo rm -rf 7.0.10
/usr/local/share/dotnet/host/fxr$ ls
7.0.13
Make a one-time donation
Make a monthly donation
Make a yearly donation
Choose an amount
Or enter a custom amount
Your contribution is appreciated.
Your contribution is appreciated.
Your contribution is appreciated.
DonateDonate monthlyDonate yearlyGitHub Authentication
- Username & Password (risky)
- Personal Access Tokens
- SSH Keys
- Deploy Keys
Added Security Options
- Two Factor Authentication (MFA)
- SAML SSO
- Active Directory Federation Services (ADFS)
- Microsoft Entra ID
- Okta
- OneLogin
- PingOne
- Others…
- LDAP
- Active Directory
- Oracle Directory Server Enterprise Edition
- OpenLDAP
- Open Directory
- Others…
JavaScript Dates
new Date() is a JavaScript object containing a number that represents milliseconds since 1/1/1970 UTC. Also defined as the number of milliseconds that have elapsed since the ECMAScript epoch (equivalent to the UNIX epoch) of 1/1/1970.
Interesting Note:
A number in ECMAScript can represent all integers from -9,007,199,254,740,992 to 9,007,199,254,740,992. The time value is something less than that: -8,640,000,000,000,000 to 8,640,000,000,000,000 milliseconds. This works out to approximately -273,790 to 273,790 years relative to 1970. (Reference 21.4.1.1 ECMAScript).
Keep in mind: the month is zero based. All others are 1 based. Example:
let date = new Date(2022,3,29,14,1,30,50);
The integer “3” for the month parameter is not March, but April.
Getters return the time zone of the machine the code is running on. There is the UTC version of the date getters.
ECMAScript 6 Classes
ECMAScript 6 introduces “class” keyword in JavaScript. It will work in almost all browsers except IE. Everything one can do using class to create JavaScript classes can also be done with JavaScript constructor functions (the classic way). It just looks cleaner and less typing.
Here is how to create a JavaScript class using the class keyword:
'use strict';
(function() {
class Person {
constructor (firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get fullName() {
return this.firstName + ' ' + this.lastName;
}
set fullName(fullName) {
var nameArray = fullName.split(' ');
this.firstName = nameArray[0];
this.lastName = nameArray[1];
}
isAdult() {
return this.age >= 18;
}
};
})();
Here is the classic way using a constructor function:
'use strict';
(function() {
function Person (firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.isAdult = function() {
return this.age >= 18;
}
Object.defineProperty(this, 'fullName', {
get: function() {
return this.firstName + ' ' + this.lastName
},
set: function(fullName) {
var nameArray = fullName.split(' ');
this.firstName = nameArray[0];
this.lastName = nameArray[1];
},
enumerable: true
});
}
})();
One thing to note: If we were to display any Person using the class example, we would not be seeing the fullName property. That is because it is not enumerable using the “class” keyword. To iterate over the properties (or keys) in the class, we would have to use the Object.defineProperty() method to make fullName enumerable.
The other interesting thing about JavaScript classes is the fullName property (defined using getter and setters) reside on the prototype. Therefore, if we were to modify the fullName property to be enumerable, we would pass the prototype object in Object.defineProperty() method:
'use strict';
(function() {
class Person {
constructor (firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get fullName() {
return this.firstName + ' ' + this.lastName;
}
set fullName(fullName) {
var nameArray = fullName.split(' ');
this.firstName = nameArray[0];
this.lastName = nameArray[1];
}
isAdult() {
return this.age >= 18;
}
};
Object.defineProperty(Person.prototype, 'fullName', {enumerable: true});
})();
The firstName, lastName, and age properties are instance properties.
Inheritance in JavaScript Classes
Use the “extends” and “super” keywords when inheriting other classes.
'use strict';
(function() {
class Person {
constructor (firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get fullName() {
return this.firstName + ' ' + this.lastName;
}
set fullName(fullName) {
var nameArray = fullName.split(' ');
this.firstName = nameArray[0];
this.lastName = nameArray[1];
}
isAdult() {
return this.age >= 18;
}
};
Object.defineProperty(Person.prototype, 'fullName', {enumerable: true});
class Student extends Person {
constructor (firstName, lastName, age) {
super(firstName, lastName, age); //Calls the Person constructor!
this._enrolledCourses = [];
}
enroll(courseId) {
this._enrolledCourses.push(courseId);
}
getCourses() {
return this.fullName + ' is enrolled in courses: ' +
this._enrolledCourses.join(', ');
}
}
let john = new Student('John', 'Doe', 44);
john.enroll('CS101');
john.enroll('EN101');
display(john);
display(john.getCourses());
})();
In the above example, the Student class inherits from Person.
Student {
firstName: John
lastName: Doe
age: 44
_enrolledCourses: CS101,EN101
fullName: John Doe
}
John Doe is enrolled in courses: CS101, EN101
The Student instance “john” has inherited all the Person properties (firstName, lastName, age, fullName).
Make a one-time donation
Make a monthly donation
Make a yearly donation
Choose an amount
Or enter a custom amount
Your contribution is appreciated.
Your contribution is appreciated.
Your contribution is appreciated.
DonateDonate monthlyDonate yearlyJavaScript Prototypes and Inheritance
Function Prototypes and Object Prototypes.
A function’s prototype is the object instance that will become the prototype for all objects created using this function as a constructor.
When a function is created, there is an object created in memory and is connected to the function behind the scenes. Each time an object instance is created using that constructor function, the “.__proto__” prototype for each of the objects point to the same object in memory for the constructor function prototype.

Let’s update the Dog prototype and add an age property:

The “patchy” instance age automatically updates. To further demonstrate that the function prototype object is the same across all instances, let us update the .__proto__ age value on the patchy instance:

So far, these are the prototype properties. What would happen if we updated the age property (not the __proto__.age) on the patchy instance?

“patchy.age” is an instance property, not a prototype property. JavaScript will examine the object and see if it has an age property. In the first display(patchy.age), the instance does not have an age property. JavaScript then examines the object prototype for an age property. In this case patchy.__proto__ has an age property with a value of 8. After we updated the patchy.age property to 10, what really happened, is we added an instance property of age, to the patchy object. In the second display(patchy.age), JavaScript checks the object instance for an age property. It finds one and displays its value of 10. We can see, the patchy instance has access to both its own “age” property, and it’s __proto__ “age” property.
Using the “hasOwnProperty” we can further look into this.

An object’s prototype is the object instance from which the object is inherited.
In the previous examples, the “patchy” has been inheriting from the Dog prototype object. The prototype is also inheriting from the Object prototype. There are multiple levels of inheritance at work. The inheritance chains can be shown as follows:

The following code demonstrates how to put inheritance chains to work so our objects can inherit prototype properties from other objects:
'use strict';
(function() {
function Person (firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
Object.defineProperty(this, 'fullName', {
get: function() {
return this.firstName + ' ' + this.lastName
},
enumerable: true
});
}
function Student(firstName, lastName, age) {
Person.call(this, firstName, lastName, age);
this._enrolledCourses = [];
this.enroll = function(courseId) {
this._enrolledCourses.push(courseId);
};
this.getCourses = function() {
return this.fullName + ' is enrolled in: ' +
this._enrolledCourses.join(', ');
};
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
let homer = new Student('Homer', 'Simpson', 45);
homer.enroll('CS301');
homer.enroll('EN101');
homer.enroll('CH101');
display(homer.getCourses());
display(Student.prototype.constructor);
})();
Creating JavaScript Objects
2 ways: Object literals, and constructor functions.
Both use Object.create() behind the scenes. Object.create() is very verbose. The object literal, and construct functions are easier, and more readable to use.
Object Literals
let person = {
firstName : "John",
lastName : "Doe",
profileColor : "Red",
isProfileColorBlue() { return this.profileColor === "Blue"}
};
Constructor Functions
function Person(firstName, lastName, profileColor) {
this.firstName = firstName;
this.lastName = lastName;
this.profileColor = profileColor;
this.isProfileColorBlue = function() {
return this.isProfileColor === "Blue";
}
}
Lack of Microsoft Support
Yes, I am voicing my grievances with Microsoft.
I downloaded Windows 10 Enterprise from MSDN through the subscription we pay for.
Ran setup to update Windows 8.1 which was downloaded and activated from MSDN also.
So, after the upgrade, I see it is saying that “Windows is not activated”. I click the link in at the bottom of the desktop, and I get the activation window with a nice “Activate” button. So, I click it.
I get a message saying activation failed, and to try again later. Leads me to believe there was an internet connection that was down. So I open IE and do a search. No problem there.
I go back and click “Activate” again. Same error. I go to work and come home. I try again. Same error. I start searching the web. There is talk of running this and that, but there is this nice “Change Activation Code” button. Seems reasonable.
I go to MSDN, and copy an activation key. I click the Change Code button hoping I can use the MSDN provided activation key. The window freezes up. I have to force it to shut down and try again Start > Settings > activation… Same problem: I get these cute ding noises they have which I assume means it is stuck, the window is frozen, so I search MSDN and they have a link in a Windows 10 activation MSDN article for contacting support if clicking the “Activate” key or “Change Activation Code” does not resolve the issue. So I click it.
I end up on a page with number of choices. I chose the online chat. They referred me to MSDN!! with a phone number!
An hour has passed by now and I’m frustrated!
I give a horrible rating to the feedback popup.
I do some more searching… Padget46 in an MSDN social posting:
says to try Slui 04… Sounds reasonable. It is a window that walks you through a phone activation! Eureka! success!!!
No so fast… I call and enter the 9 groups of numbers. The recorded voice says I have an invalid copy of windows and should return it!!!! WHAT??? I downloaded the .iso from MSDN!?!
I am steaming mad…
I do some more searching and thank you to:
SOLVED: Windows Can’t Be Activated Right Now 0x8007232b – Windows 8
This Canadian explained all the Slui’s and slui 03 allowed me enter the MSDN provided activation key!
Microsoft,
Your activation process is dismal. It was the singular most dismal experience ever. It makes me root for Apple, as with each and every OS upgrade, It was a click of a button, Agree to terms, wait, login.
When I have to spend 3 hours total to upgrade to Windows 10 when it was downloaded through my MSDN subscription, and the support comes from a Canadian, Not only do I feel mad, and frustrated but I wish Apple runs you out the market!!!
It is also the motivation for writing this blog post, and the very small thing I can do to get my voice heard. I hope this gets picked up and see’s the light of day, especially to Mr. Satya Nadella. I had conceded to my Microsoft fans at work that from what I read about mr. Nadella’s direction for Microsoft, I am hopeful that they will come around and provide a better experience. When my brother-in-law showed me all the great things about windows 10, I was excited to try it.
I take back all of what I said. This singular experience has put me squarely back in the “Apple has the best experience” camp, and I will reserve judgement on whether windows 10 is any better till I get to use it.
With that said, I hope this also helps others experiencing the same problems, because there was no help from Microsoft. Ironically, I cannot compare it Apple tech support as I have never had any issues that warranted a call to Apple Support. They were easily solved by information popups in the OS, or easily found and relevant online.
Leave a Comment