Nutshell Series

πŸ”§ Dependency Injection (DI) Explained: Transient vs Scoped vs Singleton

Dependency Injection (DI) is a design pattern that simplifies how objects and their dependencies are managed in an application. Instead of classes creating their own dependencies, DI provides those dependencies from the outside. This makes applications cleaner, testable, and maintainable.

βš™οΈ What is Dependency Injection?

At its core, DI is about inversion of control: your classes don’t create what they need; a container provides them. This container decides:

  • How to create objects
  • When to reuse objects
  • How to dispose of them when no longer needed

πŸ“Œ Service Lifetimes

When you register services in a DI container, you usually choose a lifetime:

  • Transient – A new instance is created every time it’s requested.
  • Scoped – One instance is created per request (or unit of work).
  • Singleton – A single instance is shared across the entire application lifetime.

πŸ”„ Transient

A new instance is created each time the service is requested. Best for lightweight, stateless services.

// Example in C#
services.AddTransient<IEmailService, EmailService>();

πŸ“‚ Scoped

A new instance is created once per request, but reused within that request. Useful for services like database contexts.

// Example in C#
services.AddScoped<IDbContext, AppDbContext>();

β™Ύ Singleton

A single instance is created and reused for the entire lifetime of the application. Perfect for loggers, configuration readers, and caching providers.

// Example in C#
services.AddSingleton<ILogger, Logger>();

πŸ“Š When to Use Each?

  • Transient – For short-lived, stateless operations (e.g., helpers, formatters).
  • Scoped – For services tied to a single request or unit of work (e.g., DbContext).
  • Singleton – For shared state or expensive-to-create services (e.g., loggers, configuration, caching).

πŸš€ Conclusion

Dependency Injection ensures better code structure, easier testing, and improved flexibility.
Choosing the right lifetime β€” Transient, Scoped, or Singleton β€” helps you balance performance with resource management.

Nutshell Series

Fixing Azure Token Issuer Mismatch Error: β€œPrimary Access Token is from the Wrong Issuer”

I recently ran into a frustrating Azure authentication error while working with ARM (Azure Resource Manager) APIs.
The error looked like this:

Cache-Control: no-cache
Pragma: no-cache
WWW-Authenticate: Bearer authorization_uri="https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", error="invalid_token", error_description="The primary access token is from the wrong issuer. It must match the tenant associated with this subscription. Please use correct authority to get the token."
x-ms-failure-cause: gateway
x-ms-request-id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

The Problem

The critical clue was:

The primary access token is from the wrong issuer. It must match the tenant associated with this subscription.

When I decoded the token using JWT.io, the iss (issuer)
claim was:

f8cdef31-a31e-4b4a-93e4-5f571e91255

That GUID is the Microsoft Services tenant β€” it appears when you sign in with a personal Microsoft account (MSA).
My Azure subscription, however, was tied to a specific Azure Active Directory (AAD) tenant, so Azure rejected the token because the issuer didn’t match.

What Caused It

  • I logged in using a personal Microsoft account (MSA).
  • The subscription belonged to an Azure AD tenant (not the Microsoft Services tenant).
  • Using VisualStudioCodeCredential or DefaultAzureCredential still returned tokens from the wrong issuer because the underlying login session was wrong.

Solution β€” Steps to Fix

The fix is straightforward: log into the correct tenant, set the subscription, and use credentials that respect the CLI session.

1) Log in to the correct tenant

az login --tenant <your-tenant-id>

2) Set the subscription

az account set --subscription <your-subscription-id-or-name>

3) Use Azure CLI credentials in C#

Instead of DefaultAzureCredential, switch to AzureCliCredential and fetch the token directly (this uses the Azure CLI credentials stored during az login β€” so make sure you’re logged in from the terminal):

// using Azure.Identity and Azure.Core
// var credential = new DefaultAzureCredential();
var credential = new AzureCliCredential();

string[] scopes = new[] { "https://management.azure.com/.default" };

var token = (await credential.GetTokenAsync(new TokenRequestContext(scopes))).Token;

// Optional alternative with explicit cancellation token
// token = (await credential.GetTokenAsync(new TokenRequestContext(scopes),
//     System.Threading.CancellationToken.None)).Token;

Note: This uses Azure CLI credentials stored during az login, so ensure you are logged in to the correct tenant and subscription in your terminal before running this code.

Key Takeaways

  • If your JWT iss claim is f8cdef31-a31e-4b4a-93e4-5f571e91255, you’re using a Microsoft Services tenant token (MSA) β€” it won’t work for subscriptions tied to an Azure AD tenant.
  • Fix the login by targeting the correct tenant with az login --tenant <tenant-id> and then set the subscription with az account set --subscription <subscription-id-or-name>.
  • Using AzureCliCredential in C# picks up tokens from your active Azure CLI session and helps avoid issuer mismatch issues.
Nutshell Series

πŸ” Azure AD App: Set Long-Term Secret (Two Easy Ways)

Need a long-lasting client secret for a non-production app? Here are two ways to create a secret that mimics no expiry β€” ideal for automation, CI/CD, or UAT setups.

βœ… Option 1: Azure CLI

Use this for a quick and easy credential reset:

az ad app credential reset --id ********-****-****-****-************ --years 299 --append --display-name uat-automation-secret-longterm
  • --years 299: Secret valid for ~299 years
  • --append: Keeps existing secrets
  • --display-name: Helps identify the secret

πŸ”„ Option 2: Microsoft Graph API (addPassword)

You can also use Microsoft Graph’s addPassword endpoint for full control.

POST Request

POST https://graph.microsoft.com/v1.0/applications/{app-id}/addPassword
Authorization: Bearer <token>
Content-Type: application/json

Request Body

{
  "passwordCredential": {
    "displayName": "uat-automation-secret-longterm",
    "endDateTime": "2324-07-17T23:59:59Z"
  }
}

Tip: endDateTime is in UTC format. Set a far future date (e.g., 299 years ahead) to mimic “no expiry”.

⚠️ Security Reminder

  • Use only in non-production scenarios
  • Store secrets in Key Vault, not in code
  • Prefer Managed Identity or Federated Credentials for production

Both methods are effective β€” choose the one that fits your environment or automation strategy.

Nutshell Series, Security

πŸ” Common Security Testing Terminologies

Term Full Form Purpose Category
SAST Static Application Security Testing Analyzes code or binaries to find vulnerabilities before runtime. Static
Secure Code Review β€” Manual or automated inspection of code for security flaws. Static
DAST Dynamic Application Security Testing Simulates attacks on a running application to find security issues. Dynamic
Fuzzing Fuzz Testing Sends malformed or random data to discover crashes and bugs. Dynamic
Pen Testing Penetration Testing Ethical hacking to uncover and exploit real-world vulnerabilities. Dynamic
IAST Interactive Application Security Testing Combines SAST and DAST with real-time analysis via instrumentation. Hybrid
RASP Runtime Application Self-Protection Monitors and protects applications in real-time during execution. Hybrid
SCA Software Composition Analysis Identifies vulnerabilities in open-source and third-party components. Component-based
VAPT Vulnerability Assessment and Penetration Testing Combines scanning and exploitation to assess security posture. Operational
Threat Modeling β€” Identifies and prioritizes threats early in the development lifecycle. Operational
Bug Bounty β€” Rewards external security researchers for responsibly reporting vulnerabilities. Operational
Nutshell Series, Security

🧾 SAST vs DAST Comparison

Feature SAST (Static Application Security Testing) DAST (Dynamic Application Security Testing)
Testing Type White-box Black-box
Access to Code Required (analyzes source code or binaries) Not required (tests from outside the app)
When Used Early in SDLC (during coding/build phase) Later in SDLC (during or after deployment)
What It Tests Source code, bytecode, or binaries Running application, web interfaces, APIs
Finds Code-level issues (e.g., SQL injection, secrets) Runtime issues (e.g., logic flaws, auth problems)
False Positives Higher (due to theoretical analysis) Lower (based on real execution)
Speed Fast (no need to run the app) Slower (requires deployed app and interactions)
Tool Examples SonarQube, Checkmarx, Fortify OWASP ZAP, Burp Suite, Acunetix
Language Dependency Language-specific Language-agnostic
Use Case Secure code review, CI/CD integration Real-world attack simulation, post-deployment testing
Nutshell Series

Fixing Logic App VNet Integration: “Access to the path ‘C:\home\data\Functions\secrets\Sentinels’ is denied.”

If you’re integrating Azure Logic Apps Standard with a VNet and private endpoints, you may encounter this nasty error after deploying your app or modifying your networking configuration:

Access to the path ‘C:\home\data\Functions\secrets\Sentinels’ is denied.

Despite following Microsoft’s recommended steps, the issue may persist. In this post, I’ll break down the actual root causes, explain why the error happens, and offer a practical trick that can resolve it, especially after switching from public to private networking.

πŸ” Root Cause

This error usually happens when:

  • Your Logic App is moved from public access to a VNet-integrated private network.
  • The storage account (used to host runtime content and secrets) has private endpoints enabled, but DNS or firewall rules aren’t set up properly.
  • Deployment tools like ARM or Terraform don’t handle the WEBSITE_CONTENTOVERVNET setting correctly during creation.

βœ… Microsoft Recommendations to Try First

  1. Enable WEBSITE_CONTENTOVERVNET = 1 in Configuration settings of the Logic App.
  2. Ensure the storage account has:
    • VNet access with correct subnet delegations
    • Private DNS zone linked to your VNet (file, blob, queue, table)
  3. Enable β€œAllow storage account key access” in the storage account’s Configuration blade.
  4. If using ARM or Terraform:
    • Separate your appSettings into a nested resource of type [Microsoft.Web/sites/config]

But here’s the truth: Even after doing all this, the error may still appear.

πŸ› οΈ Trick That Actually Works

If you’re stuck and everything seems configured correctly, try this workaround that’s helped in many real-world deployments:

πŸ’‘ Scale up your Logic App to WS2 tier temporarily and then scale it back down to WS1.

Why this works:

When switching from public to private storage/VNet, the Logic App runtime may get β€œstuck” in an inconsistent state, especially regarding storage path mounting or internal config sync.

Scaling up to WS2 forces:

  • A runtime refresh
  • A full reinitialization of the hosting environment
  • Resync of private DNS/storage endpoints

πŸš€ Step-by-Step: Fix It

  1. Go to your Logic App resource.
  2. Navigate to Scale Up blade.
  3. Change SKU to WS2 (higher tier) and hit Apply.
  4. Wait until the deployment is successful (1–2 mins).
  5. Now go back and revert the SKU back to WS1.

βœ… After this step, your Logic App should restart and mount the secret paths correctly.

🧠 Final Thoughts

This issue is not well-documented, but it’s common when moving to private networking in enterprise deployments. Logic Apps tightly depend on the underlying storage account, and improper sync between the app’s network context and the storage endpoints can lead to the above error.

Scaling the app up and down is a safe way to force the platform to re-establish all bindings.

πŸ“Œ Quick Checklist

  • βœ… VNet Integration configured
  • βœ… Private endpoints enabled for Storage Account
  • βœ… Private DNS zones linked
  • βœ… WEBSITE_CONTENTOVERVNET = 1
  • βœ… Allow storage account key access
  • βœ… Storage access via system-assigned managed identity
  • βœ… Scale-up and scale-down trick applied

πŸ’¬ Have You Faced This?

Drop your experience or questions in the comments β€” Azure networking errors can be painful, but you’re not alone!

Nutshell Series

Power Query vs SQL Joins

The following table compares Power Query Join Kinds with their equivalent SQL Join types. Each join kind is explained with a visual icon and SQL analogy.

Join Kind Icon Description SQL Equivalent
Left Outer

Returns all rows from the left table and matching rows from the right. Non-matching right rows are set to null. LEFT JOIN
Right Outer

Returns all rows from the right table and matching rows from the left. Non-matching left rows are set to null. RIGHT JOIN
Full Outer

Returns all rows from both tables. Where there’s no match, nulls are inserted. FULL OUTER JOIN
Inner

Returns only rows with matching values in both tables. INNER JOIN
Left Anti

Returns rows from the left table that have no match in the right table. LEFT JOIN ... WHERE right.id IS NULL
Right Anti

Returns rows from the right table that have no match in the left table. RIGHT JOIN ... WHERE left.id IS NULL
Full Outer Anti

Returns all rows from both tables where there’s no matches

FULL OUTER JOIN ... WHERE left.id IS NULL AND right.id IS NULL

Nutshell Series

πŸ” Struggling with Connect-ExchangeOnline Errors in PowerShell? Here’s How I Solved It!


If you’ve ever tried to connect to Exchange Online using PowerShell and hit a brick wall, you’re not alone. I recently ran into two frustrating errors while using Connect-ExchangeOnline, and after a lot of head-scratching (and Googling), I finally found a clean, working solution.

Let me walk you through what went wrong and how you can fix it β€” especially if you’re working in a non-interactive or automation-heavy environment.


⚠️ Error #1: β€œA window handle must be configured”

This was the first error I got when running a simple connection command:

A window handle must be configured. See https://aka.ms/msal-net-wam#parent-window-handles

This usually happens when PowerShell tries to use Windows Web Account Manager (WAM) to launch a browser-based login β€” but there’s no interactive UI available. If you’re running a script in a headless setup (like Azure Automation, GitHub Actions, or a remote server), this error is a dead end.

πŸ”§ Tried Fix: Using -DisableWAM

Disabling WAM seemed like a logical next step. I ran:

Connect-ExchangeOnline -DisableWAM

But that only led me straight into this new error:

Failed to connect to Exchange Online: An HttpListenerException occurred while listening on http://localhost:49747/ for the system browser to complete the login.

It also suggested running this from an admin shell:

netsh http add iplisten 127.0.0.1

But honestly? That felt like duct-taping the problem instead of solving it.


βœ… The Real Fix: Use an Access Token Instead

After some digging, I found a better way β€” one that doesn’t depend on browser pop-ups, localhost listeners, or WAM. The trick is to generate an access token using your Azure AD app and pass it directly to the Connect-ExchangeOnline command.

πŸ“Œ Step 1: Register an Azure App

  1. Go to Azure Portal β†’ App Registrations.
  2. Create a new app registration.
  3. Under “API Permissions”, add Exchange.ManageAsApp.
  4. Create a client secret or upload a certificate (for secure token access).

πŸ›  Step 2: Generate Access Token via PowerShell

$tenantId = "<your-tenant-id>"
$clientId = "<your-client-id>"
$clientSecret = "<your-client-secret>"
$scope = "https://outlook.office365.com/.default"

$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" `
    -Body @{
        client_id     = $clientId
        scope         = $scope
        client_secret = $clientSecret
        grant_type    = "client_credentials"
    }

$accessToken = $tokenResponse.access_token

πŸ”— Step 3: Connect Using the Token

Connect-ExchangeOnline -AccessToken $accessToken -Organization "<your-tenant-domain>"

And that’s it β€” no browser, no WAM, no port listeners. Just a clean, programmatic login.


πŸ’‘ Pro Tips

  • This method is great for automation scripts in environments like Azure Automation, GitHub Actions, or even headless servers.
  • Make sure your app has the right permissions and you’ve granted admin consent in Azure AD.
  • This method is meant for admin tasks, not user mailbox actions (like reading emails).

🧩 Wrapping Up

If you’re facing authentication issues with Connect-ExchangeOnline, don’t waste hours trying to debug listener ports or browser issues. Switching to access token-based authentication saved me so much time β€” and now my scripts run flawlessly, even in automated pipelines.

Got questions? Drop them in the comments below β€” happy to help!

Nutshell Series

Complete List of DNS Record Types and Their Purpose

DNS (Domain Name System) records are instructions stored in authoritative DNS servers that provide information about a domain, such as its IP address, mail servers, and other services. Understanding different DNS record types is essential for managing domains and configuring networks efficiently.

πŸ“Œ DNS Record Types Explained

Record Type Full Form Purpose
A Address Record Maps a domain to an IPv4 address.
AAAA IPv6 Address Record Maps a domain to an IPv6 address.
CNAME Canonical Name Alias of one domain to another (no IP).
MX Mail Exchange Specifies mail server for receiving emails.
TXT Text Holds human-readable notes, SPF, DKIM, DMARC records.
NS Name Server Specifies authoritative name servers for domain.
SOA Start of Authority Provides domain metadata: serial number, refresh, retry, etc.
PTR Pointer Used for reverse DNS lookups (IP β†’ domain).
SRV Service Locator Specifies host and port for specific services.
CAA Certification Authority Authorization Specifies which CAs are allowed to issue certificates.
NAPTR Name Authority Pointer Used in conjunction with SRV records for VoIP, SIP, ENUM.
DNSKEY DNS Public Key Contains public keys used in DNSSEC.
DS Delegation Signer Used to secure delegation in DNSSEC.
RRSIG Resource Record Signature Cryptographic signature for DNSSEC data.
NSEC Next Secure Record Used in DNSSEC to prove a record does not exist.
NSEC3 Next Secure Record v3 Improved DNSSEC denial of existence.
TLSA Transport Layer Security Authentication Used with DANE to associate TLS certificates with domain names.
SPF Sender Policy Framework Defines authorized email servers. Deprecated in favor of TXT.
LOC Location Specifies geographical location of a host.
HINFO Host Information Specifies CPU and OS type of a host (rarely used).
RP Responsible Person Provides email address of the person responsible for the domain.
AFSDB AFS Database Specifies servers for AFS (Andrew File System).
X25 X.25 Address Maps domain to an X.25 address (obsolete).
ISDN ISDN Address Maps domain to an ISDN number (obsolete).
KEY Key Record Used for cryptographic keys in DNSSEC (deprecated).
SIG Signature Record Used to store digital signatures in DNSSEC (deprecated in favor of RRSIG).

Note: Not all record types are commonly used. DNSSEC-related records (like DNSKEY, DS, RRSIG) are crucial for securing DNS. Legacy types like X25 and ISDN are mostly obsolete today.

Nutshell Series

πŸ“‘ Ultimate Guide to Standard Port Numbers and IP Address Ranges

In today’s digital landscape, ports and IP addresses form the backbone of all network communication. Whether you’re configuring a server, firewall, or cloud resource, understanding standard ports and IP ranges is essential.


πŸ”’ Port Number Ranges

Range Description Port Numbers
Well-known ports Assigned to core services (HTTP, DNS, etc.) 0 – 1023
Registered ports Assigned to specific apps/services 1024 – 49151
Dynamic/Ephemeral ports Used for temporary communications 49152 – 65535

🌐 Common TCP/UDP Ports

Port Protocol Service
20 TCP FTP Data Transfer
21 TCP FTP Control
22 TCP SSH
23 TCP Telnet
25 TCP SMTP
53 TCP/UDP DNS
67 UDP DHCP Server
68 UDP DHCP Client
69 UDP TFTP
80 TCP HTTP
110 TCP POP3
119 TCP NNTP
123 UDP NTP
135 TCP/UDP Microsoft RPC
137–139 TCP/UDP NetBIOS
143 TCP IMAP
161 UDP SNMP
162 UDP SNMP Trap
179 TCP BGP
389 TCP/UDP LDAP
443 TCP HTTPS
445 TCP SMB
465 TCP SMTPS
500 UDP IPsec IKE
514 UDP Syslog
515 TCP LPD
587 TCP SMTP (Auth)
631 TCP/UDP IPP
636 TCP LDAPS
873 TCP rsync
993 TCP IMAPS
995 TCP POP3S
1080 TCP SOCKS Proxy
1433 TCP Microsoft SQL Server
1434 UDP SQL Server Browser
1521 TCP Oracle DB
1701 UDP L2TP VPN
1812 UDP RADIUS Auth
1813 UDP RADIUS Accounting
1883 TCP MQTT
2049 TCP/UDP NFS
2375 TCP Docker (non-TLS)
2376 TCP Docker (TLS)
3306 TCP MySQL
3389 TCP RDP
3690 TCP Subversion
4369 TCP Erlang Port Mapper
5000 TCP Flask / Docker Registry
5060 TCP/UDP SIP
5061 TCP SIP over TLS
5432 TCP PostgreSQL
5671 TCP AMQP over TLS
5672 TCP AMQP (RabbitMQ)
5900 TCP VNC
5985 TCP WinRM (HTTP)
5986 TCP WinRM (HTTPS)
6379 TCP Redis
8080 TCP HTTP Alternate
8443 TCP HTTPS Alternate
9000 TCP SonarQube / PHP-FPM
9090 TCP Prometheus
9200 TCP Elasticsearch (API)
9300 TCP Elasticsearch (Cluster)
11211 TCP/UDP Memcached
27017 TCP MongoDB

🌍 IP Address Ranges Explained

πŸ” Private IP Ranges (RFC 1918)

Class Range CIDR IPs
A 10.0.0.0 – 10.255.255.255 10.0.0.0/8 16.7 million
B 172.16.0.0 – 172.31.255.255 172.16.0.0/12 1 million
C 192.168.0.0 – 192.168.255.255 192.168.0.0/16 65,536

🌐 Public IP Addresses

Any IP address not in the above private ranges is considered public and routable on the internet.

Example Public IPs:

  • 8.8.8.8 (Google DNS)
  • 1.1.1.1 (Cloudflare DNS)

πŸ“˜ Quick Reference Table

Category Range or Example
Well-known Ports 0 – 1023
Registered Ports 1024 – 49151
Dynamic/Ephemeral 49152 – 65535
Private IP (Class A) 10.0.0.0 – 10.255.255.255
Private IP (Class B) 172.16.0.0 – 172.31.255.255
Private IP (Class C) 192.168.0.0 – 192.168.255.255
Public IPs Anything outside private ranges