Code and Concepts
Code Explanation
app.UseCookieAuthentication(new CookieAuthenticationOptions());
- Purpose: This creates and spins up the Cookie Authentication Middleware inside the OWIN pipeline.
- What it does:
- It intercepts incoming HTTP requests to look for your application's authentication cookie.
- If it finds a valid cookie, it decrypts it, extracts the user's claims (like their name, email, or
access_token), and populatesHttpContext.User(orClaimsPrincipal.Current). - If you log out, it handles deleting that cookie from the user's browser.
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
- Purpose: This acts as a bridge that connects the OIDC middleware to the Cookie middleware.
- What it does:
- It tells the OIDC middleware: "Once you successfully validate the ID Token from Azure, automatically hand over the user's claims to the Cookie middleware."
- The Cookie middleware then packages those claims into a secure cookie and drops it into the user's browser.
- Without this line, the OIDC validation would succeed, but your application wouldn't know where to save the login state, forcing the user into an infinite login loop.
app.UseOpenIdConnectAuthenticationinitializes and injects the OpenID Connect (OIDC) Middleware into your OWIN pipeline. Its primary purpose is to outsource user authentication to an external Identity Provider (like Microsoft Entra ID)
Key Responsibilities of app.UseOpenIdConnectAuthentication
- Automatically Handling Redirection (The Challenge)
When an unauthenticated user hits a globally protected route (e.g., via [Authorize]), this middleware intercepts the request. It automatically generates the secure Azure login URL and redirects the user's browser to Microsoft Entra ID.
- Protocol Validation & Security Compliance
When Azure redirects the user back to your app with tokens or authorization codes, this middleware catches that incoming request. It automatically:
- Downloads Azure's public signing keys via metadata endpoints (
/.well-known/openid-configuration). - Verifies that the
id_tokensignature is authentic and untampered with. - Ensures the token hasn't expired and was issued specifically to your
ClientId.
- Transforming Tokens into Identity Claims
Once the token is validated, the middleware extracts the user's profile data (like their name, unique ID, and email) out of the JWT token string. It maps this data into a standard .NET ClaimsIdentity object, making the user's details natively readable by your application code via User.Identity.
- Handling Cross-Site Handshakes (Logouts)
It listens for logout requests. When you trigger a sign-out, it clears your local app cookies and automatically redirects the user to Azure's logout endpoint, ensuring they are signed out globally across both your system and Microsoft Entra ID.
[ Incoming Request ] │ ▼
- Cookie Middleware ──(Has valid cookie?)──► Yes ──► [ Access Granted ] │ No ▼
- OIDC Middleware ──(Redirects to Azure)──► [ User Logs in at Azure Portal ] │ │ ◄──────────────────(Returns Token/Code)────────────────┘ │
- OIDC Validates Token ──► Converts to Claims ──► Saves via Cookie Middleware
What is ResponseType?
ResponseType tells the identity provider (Microsoft Entra ID) what security artifacts it must send back to your application immediately after the user successfully logs in via the browser. It determines which OAuth 2.0 / OIDC flow your app will use.
Possible Values for ResponseType
In ASP.NET Framework 4.8, these values are typically assigned using the string constants found in Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectResponseType.
| Value / Constant | Flow Name | Description | Use Case |
|---|---|---|---|
"id_token"IdToken |
Implicit Flow | Azure returns only a signed JWT identity token. No access token is provided, and no client secret is used. | Good for basic authentication (sign-in only) without back-end API requirements. |
"code"Code |
Authorization Code Flow | Azure returns an authorization code. Your application must exchange this code for access/refresh tokens using a secure HTTP POST back-channel request. | Standard, highly secure flow for web applications that access protected APIs. |
"id_token token"IdTokenToken |
Implicit Flow | Azure returns both the identity token and the access token directly through the browser redirect URI. | Quick sign-in and API access without using a server-side client secret. |
"code id_token"CodeIdToken |
Hybrid Flow | Azure returns an identity token immediately for local authentication, along with an authorization code to securely request access tokens later. | Standard approach for secure server-side web apps needing immediate sign-in and API tokens. |
What is Scope?
Scope defines the permissions and resources your application is requesting from Microsoft Entra ID. It acts as a selector to tell Azure what information to include inside the id_token and what APIs the access_token is allowed to call. Multiple scopes are separated by spaces (e.g., "openid profile").
Possible Values for Scope
Scopes are split into two categories: OIDC Standard Scopes (for user info) and API Scopes (for accessing services like Microsoft Graph or your own custom API APIs).
- OpenID Connect Standard Scopes
These control what user data is baked directly into the id_token:
"openid"(Mandatory): Tells Azure that the request is an OpenID Connect sign-in. Without this, Azure treats the request as a basic OAuth 2.0 flow and won't return anid_token."profile": Requests basic user information claims like name, given name, family name, and preferred username."email": Requests the user's email address claim if available."offline_access": Requests a Refresh Token. This allows your back-end server to silently request new access tokens when old ones expire, without forcing the user to log in again.
- Downstream API Scopes (Microsoft Graph Examples)
If you want your application to act on behalf of the user to look up data in Microsoft 365 or Azure, you append Graph scopes:
"user.read": Allows your app to read the profile of the signed-in user (e.g., photo, job title, manager)."directory.read.all": Allows your app to read directory data like corporate groups and organization structure.
- Custom API Scopes If your web application needs to call your own protected backend Web API, you use the URI configured in your API's app registration:
"api://your-api-client-id/access_as_user"
Authorization flow and their usage
- Authorization Code Flow (with PKCE)
- How it works: The client requests a temporary authorization code via the browser, which the backend backend trades for access and refresh tokens. Modern implementations mandate PKCE (Proof Key for Code Exchange) to cryptographically prevent code interception, eliminating the strict necessity of a client secret.
- Usage: Secure server-side web applications (like ASP.NET Core, Node.js), Single Page Applications (SPAs like Angular, React), and native Mobile/Desktop apps. This is the default gold standard for almost all modern application architectures.
- Client Credentials Flow
- How it works: The application uses its own client credentials (a
client_secretor client certificate) to authenticate directly with the identity provider’s token endpoint. No user interface or human interaction is involved. - Usage: Machine-to-machine (M2M) communications, automated background daemons, Windows services, scheduled cron jobs, and internal microservices that require application-level access rather than user-level permissions.
- Device Code Flow
- How it works: The device displays a short alphanumeric code and a verification URL to the user. The user visits the URL on a secondary device (like a smartphone or computer), logs in, enters the code, and grants access. Meanwhile, the original device polls the token endpoint until authentication succeeds.
- Usage: Input-constrained or browserless devices, such as Smart TVs, game consoles, command-line interfaces (CLI tools), and IoT hardware.
- Hybrid Flow
- How it works: The application requests multiple tokens/artifacts simultaneously from the initial browser authorization request. For example, it might request an
id_tokenimmediately via the front channel to quickly log the user into the UI, while retrieving acodeto securely trade for back-end tokens later. - Usage: Classic server-side MVC web applications (such as ASP.NET Framework 4.8 or old Java Spring apps) that require an immediate identity context alongside secure backend API connectivity.
- On-Behalf-Of (OBO) Flow
- How it works: A service takes an incoming access token sent by a client application, validates it, and exchanges it for a new access token targeted at a downstream API.
- Usage: Multi-tier microservice architectures. For instance, when a Web App calls API Service A, and API Service A needs to propagate the user's specific identity and permissions down to API Service B.
Deprecated Flows (Do Not Use in New Apps)
- Implicit Flow: Directly returns access tokens in the browser URL hash fragment. It is highly discouraged in modern development due to token leakage risks and browser cookie restrictions. Use Authorization Code Flow with PKCE instead.
- Resource Owner Password Credentials (ROPC) Flow: Requires users to type their password directly into the client application UI, which then sends the plaintext credentials to the identity provider. It violates the core separation-of-concerns principles of OAuth and breaks Multi-Factor Authentication (MFA).