Skip to main content

Azure AD B2C Custom Policy: Single Relying Party with Separate Sign-In and Sign-Up Links

Azure AD B2C Custom Policy: Single Relying Party with Separate Sign-In and Sign-Up Links

One Relying Party file. One combined page. But your application needs a standalone Sign-Up link that bypasses the combined UI and goes directly to registration. Here is the complete solution using the OAUTH-KV claim resolver and orchestration step preconditions — no duplicate RP files required.

1 RP file
Single Relying Party policy handles sign-in, sign-up, forgot password, and direct sign-up link
OAUTH-KV
Claim resolver that reads a custom query string parameter from the authorization request
Precondition
Orchestration step preconditions branch the user journey based on the action= query parameter value
?action=signup
The query parameter your app passes to signal a direct sign-up — bypass the combined page entirely
ℹ Azure AD B2C Availability Note

As of 1 May 2025, Azure AD B2C is no longer available to new customers. Existing tenants continue to operate, and this guide applies to all existing B2C tenants using custom policies. New identity implementations should evaluate Microsoft Entra External ID as the successor platform. The architectural patterns in this guide (OAUTH-KV claim resolvers, orchestration step preconditions) also apply to Entra External ID custom policies.

Understanding the Problem

Why a Standalone Sign-Up Link Does Not Work Out of the Box

The CombinedSignInAndSignUp orchestration step is the standard mechanism for presenting a single UI page that handles both authentication paths. When a user arrives at the page, the sign-in tab is active by default. There is a "Sign up now" link at the bottom of the page that users can click to switch to the registration form — but the default entry point always starts in sign-in mode.

The problem arises when your application needs to provide a standalone "Sign Up" link — a button on your home page or marketing site that takes users directly to the registration form without going through the combined page. By default, invoking the single RP policy always starts in sign-in mode regardless of what your application intends. Passing a custom query parameter like ?action=signup in the authorization URL has no effect out of the box — the Identity Experience Framework (IEF) does not read custom query parameters unless you explicitly configure it to do so.

The solution involves two things working together: the OAUTH-KV claim resolver (which extracts the custom query parameter from the OAuth 2.0 authorization request and maps it to a claim), and orchestration step preconditions (which evaluate the claim value and branch the user journey accordingly). Together, they let a single Relying Party policy produce different user journey paths based on what the application signals in the authorization URL.

Figure 1 — Complete architecture: single RP policy with three user journey paths from one authorization endpoint
Sign In linkSign Up linkForgot PasswordAPPLICATIONno ?action=?action=signupsame RP policyB2C_1A_Signup_SigninSingle RP fileOAUTH-KV:action claimPrecondition evaluationJourney branchingCombinedSignInAndSignUp pageSign-in tab active · "Sign up now" link availablePrecondition: clientActionIntent ≠ 'signup' (or absent)Direct Sign-Up page (SelfAsserted)Registration form shown immediatelyPrecondition: clientActionIntent = 'signup'Forgot Password (Sub-Journey)Triggered by "Forgot password" link on combined pageInvokeSubJourney orchestration stepAll paths → JWT Token issuedSame RP file · Same claims output · Same redirect_uriSingle policy to maintain · No policy sprawlBENEFITS✓ Zero policy sprawl✓ Single maintenance point✓ Centralised business rules✓ Same client_id / redirect_uri
All three user journeys (combined sign-in/sign-up, direct sign-up, forgot password) are served by a single Relying Party file — the OAUTH-KV claim resolver reads the ?action= parameter to decide which path to take
The Implementation

The Complete Implementation — Four XML Changes to Your Policy Files

The solution requires four changes spread across your policy files: declare the claim type in the ClaimsSchema, populate it from the OAUTH-KV resolver in the RP file, add the direct sign-up orchestration step to the user journey in Extensions, and add the precondition that skips the combined step when the claim equals "signup". Forgot Password continues to work as a sub-journey from within the combined page — no changes needed there.

1

Step 1 — Declare the claim type in TrustFrameworkExtensions.xml

Add the clientActionIntent claim type to your ClaimsSchema. This claim will hold the value of the ?action= query string parameter sent by your application. It is a plain string claim with no special constraints — it will be populated by the OAUTH-KV resolver in the next step and then evaluated by preconditions in the user journey.

Place this inside the <BuildingBlocks> <ClaimsSchema> element in your TrustFrameworkExtensions.xml or the policy file where you define your claims schema.

TrustFrameworkExtensions.xml — Step 1: Declare the clientActionIntent claim type<!-- Inside <BuildingBlocks><ClaimsSchema> -->

<ClaimType Id="clientActionIntent">
  <DisplayName>Client Action Intent</DisplayName>
  <DataType>string</DataType>
  <UserHelpText>Action intent passed by the relying party application (e.g. signup)</UserHelpText>
</ClaimType>

<!-- This claim will receive the value of ?action= from the OAuth2 authorization request -->
<!-- When action=signup is passed, it drives the precondition in the user journey -->
2

Step 2 — Populate the claim from the OAUTH-KV resolver in the Relying Party file

In your Relying Party (RP) XML file — typically named B2C_1A_Signup_Signin.xml or similar — add an InputClaim that uses the {OAUTH-KV:action} resolver as its DefaultValue. The OAUTH-KV claim resolver extracts the value of any custom query parameter passed in the OAuth 2.0 authorization request. {OAUTH-KV:action} reads ?action=signup from the URL and maps it to the clientActionIntent claim.

The AlwaysUseDefaultValue="true" attribute is critical — without it, the resolver only populates the claim if no prior value exists. With it, the resolver always overwrites the claim with the current request's value, which is what you need.

SignUpSignIn.xml (RP file) — Step 2: Map the OAUTH-KV claim resolver to clientActionIntent<!-- Inside <RelyingParty> -->

<RelyingParty>
  <DefaultUserJourney ReferenceId="SignUpOrSignIn" />

  <TechnicalProfile Id="PolicyProfile">
    <DisplayName>PolicyProfile</DisplayName>
    <Protocol Name="OpenIdConnect" />

    <InputClaims>
      <!-- Read the ?action= query parameter from the OAuth2 authorization request -->
      <!-- {OAUTH-KV:action} maps the &action= URL param to clientActionIntent claim -->
      <InputClaim
        ClaimTypeReferenceId="clientActionIntent"
        DefaultValue="{OAUTH-KV:action}"
        AlwaysUseDefaultValue="true" />
    </InputClaims>

    <OutputClaims>
      <!-- Your existing output claims (objectId, email, displayName, etc.) -->
      <OutputClaim ClaimTypeReferenceId="displayName" />
      <OutputClaim ClaimTypeReferenceId="email" />
      <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
      <!-- clientActionIntent is NOT included in output claims -->
      <!-- It is internal routing only — do not expose it in the JWT token -->
    </OutputClaims>
    <SubjectNamingInfo ClaimType="sub" />
  </TechnicalProfile>
</RelyingParty>
3

Step 3 — Modify the user journey with branching orchestration steps

This is the core of the solution. The user journey needs two orchestration steps at the beginning — one for the direct sign-up path (skipped unless clientActionIntent = signup) and one for the combined sign-in/sign-up path (skipped if clientActionIntent = signup). The preconditions on each step control which path runs.

The combined step uses a ClaimEquals precondition: if clientActionIntent equals signup, skip this step (and show the direct sign-up instead). The direct sign-up step uses the inverse: skip it unless clientActionIntent equals signup.

The Forgot Password sub-journey remains on the combined step — it is triggered by the user clicking "Forgot password" on the combined UI, not by the query parameter.

TrustFrameworkExtensions.xml — Step 3: User journey with branching preconditions<!-- Inside <UserJourneys> -->

<UserJourney Id="SignUpOrSignIn">
  <OrchestrationSteps>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 1 — Direct Sign-Up (only runs when action=signup is passed) -->
    <!-- Skip this step if clientActionIntent is absent OR not equal to signup -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="1" Type="ClaimsExchange">
      <Preconditions>
        <!-- Skip if clientActionIntent claim does not exist at all -->
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>clientActionIntent</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <!-- Skip if clientActionIntent exists but is NOT 'signup' -->
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
          <Value>clientActionIntent</Value>
          <Value>signup</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <!-- This technical profile shows only the sign-up/registration form -->
        <ClaimsExchange
          Id="DirectSignUpWithLocalAccount"
          TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 2 — Combined Sign-In / Sign-Up (normal entry point) -->
    <!-- Skip this step if action=signup was passed (direct signup ran in Step 1) -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="2" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
      <Preconditions>
        <!-- Skip the combined page if the user already completed direct sign-up in Step 1 -->
        <!-- After LocalAccountSignUpWithLogonEmail, objectId will be in the claims bag -->
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsProviderSelections>
        <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
      </ClaimsProviderSelections>
      <ClaimsExchanges>
        <ClaimsExchange
          Id="LocalAccountSigninEmailExchange"
          TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 3 — Read user from directory (after sign-in completes) -->
    <!-- Skipped if objectId already populated from direct sign-up -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="3" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange
          Id="AADUserReadWithObjectId"
          TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 4 — Issue the JWT token to the relying party -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

  </OrchestrationSteps>
</UserJourney>
4

Step 4 — Generate the authorization URLs in your application

With the policy in place, your application constructs two distinct authorization URLs — both pointing to the same RP policy, but the sign-up URL includes &action=signup as an extra parameter. MSAL automatically passes extra parameters through to B2C when you include them in the authorization request.

Application code — Authorization URLs for sign-in vs standalone sign-up (MSAL.js example)// Both links point to the SAME policy — only the extra parameter differs

// Sign-In link (standard — goes to combined page in sign-in mode)
// No ?action= parameter → clientActionIntent is empty → CombinedSignInAndSignUp runs
const signInRequest = {
  scopes: ["openid", "profile"],
  authority: "https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin"
  // No extra parameters needed for sign-in
};

// Sign-Up link (standalone — goes directly to registration form)
// ?action=signup → clientActionIntent = 'signup' → Step 1 (direct sign-up) runs
const signUpRequest = {
  scopes: ["openid", "profile"],
  authority: "https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin",
  extraQueryParameters: { action: "signup" } // This becomes ?action=signup in the auth URL
};

// Using MSAL.js — both call loginRedirect (or loginPopup) with the appropriate request
// Sign-In button: msalInstance.loginRedirect(signInRequest);
// Sign-Up button: msalInstance.loginRedirect(signUpRequest);

// Raw authorization URL structure (for non-MSAL integrations):
// Sign-In: https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/oauth2/v2.0/authorize
// ?p=B2C_1A_Signup_Signin&client_id=...&response_type=code&redirect_uri=...&scope=openid
// Sign-Up: same URL + &action=signup at the end
Figure 2 — How the orchestration step preconditions branch execution for each authorization URL
PATH A — Sign-In (no ?action= param)RP reads OAUTH-KV:action → clientActionIntent = (empty)Step 1 (Direct SignUp): SKIPPED→ ClaimsExist:clientActionIntent = false → SkipThisOrchestrationStepStep 2 (CombinedSignInAndSignUp): RUNS ✓→ objectId not in bag → precondition not triggered → step runsStep 3 (ReadUserFromDirectory): RUNS ✓Step 4 (SendClaims → JWT Token) ✓User sees combined sign-in/sign-up UISign-in tab is active by defaultPATH B — Direct Sign-Up (?action=signup)RP reads OAUTH-KV:action → clientActionIntent = 'signup'Step 1 (Direct SignUp): RUNS ✓→ claim exists + equals 'signup' → both preconditions satisfied → runsStep 2 (CombinedSignInAndSignUp): SKIPPED→ objectId now exists in bag (from Step 1) → SkipThisOrchestrationStepStep 3 (ReadUserFromDirectory): SKIPPED→ objectId exists → SkipThisOrchestrationStepStep 4 (SendClaims → JWT Token) ✓User sees sign-up registration form immediatelyNo combined page — direct registration UX
The objectId claim is the secondary guard — once a user completes sign-up in Step 1, objectId is in the claims bag. Steps 2 and 3 both check for it and skip automatically.
Adding Forgot Password via Sub-Journey

Forgot Password Sub-Journey — How It Fits In

Forgot Password works as an InvokeSubJourney orchestration step that is triggered when the user clicks "Forgot your password?" on the combined sign-in/sign-up page. In the B2C Identity Experience Framework, this click generates a special AADB2C90118 error code that your orchestration logic intercepts and routes to the sub-journey. This mechanism is independent of the clientActionIntent claim and works correctly without any additional modification to the branching logic above.

Add the Forgot Password sub-journey invocation as an additional orchestration step in your user journey. It sits between the combined step and the SendClaims step, and uses a precondition to skip unless the special forgot-password flag claim is set.

TrustFrameworkExtensions.xml — Adding Forgot Password as a sub-journey step<!-- This goes BEFORE the SendClaims step (Step 4 above becomes Step 5) -->
<!-- Add this claim declaration to ClaimsSchema first: -->
<!-- <ClaimType Id="isForgotPassword"><DataType>boolean</DataType></ClaimType> -->

<!-- Inside UserJourney — after Step 2 (CombinedSignInAndSignUp) -->

<OrchestrationStep Order="4" Type="InvokeSubJourney">
  <Preconditions>
    <!-- Only run the forgot-password sub-journey if isForgotPassword = true -->
    <!-- This claim is set when user clicks "Forgot your password?" on the combined page -->
    <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
      <Value>isForgotPassword</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <JourneyList>
    <Candidate SubJourneyReferenceId="PasswordReset" />
  </JourneyList>
</OrchestrationStep>

<!-- The PasswordReset sub-journey handles OTP verification and password reset -->
<!-- It is defined separately as a <SubJourney Id="PasswordReset"> in the extensions file -->
<!-- After the sub-journey completes, execution returns to the parent journey -->
<!-- and continues to the SendClaims step (user is signed in after password reset) -->
Figure 3 — Complete policy file structure and what goes where
TrustFrameworkBase.xmlBuilt-in technical profiles:SelfAsserted-LocalAccountSignIn-EmailLocalAccountSignUpWithLogonEmailAAD-UserReadUsingObjectIdJwtIssuerDo not modifyTrustFrameworkExtensions.xml← Changes go here:ClaimsSchema:+ clientActionIntent (string)+ isForgotPassword (boolean)UserJourneys:+ Step 1 (Direct SignUp)with preconditions+ Step 4 (ForgotPasswordInvokeSubJourney)SubJourneys: PasswordResetB2C_1A_Signup_Signin.xml← Changes go here:RelyingParty:DefaultUserJourney:ReferenceId=SignUpOrSignInTechnicalProfile:InputClaims:+ clientActionIntentDefaultValue={OAUTH-KV:action}AlwaysUseDefault=true
Three changes total: one claim declaration in Extensions, one InputClaim in the RP file, and new orchestration steps in Extensions. TrustFrameworkBase.xml is never modified.
Testing and Debugging

Testing the Policy and Debugging with Application Insights

After uploading the updated policy files, test both paths using the "Run now" feature in the Azure portal Identity Experience Framework blade. For the direct sign-up path, add &action=signup to the "Run now" test URL.

Test URLs — Use these in the Identity Experience Framework "Run now" test page# Standard sign-in / combined page (no action parameter) https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin/oauth2/v2.0/authorize
  ?client_id=YOUR-CLIENT-ID
  &nonce=defaultNonce
  &redirect_uri=https://jwt.ms
  &scope=openid
  &response_type=id_token
  &prompt=login

# Direct sign-up (action=signup triggers Step 1) https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin/oauth2/v2.0/authorize
  ?client_id=YOUR-CLIENT-ID
  &nonce=defaultNonce
  &redirect_uri=https://jwt.ms
  &scope=openid
  &response_type=id_token
  &prompt=login
  &action=signup <-- This is the key addition

# Debug with Application Insights trace logging enabled # Add &diags:{"applicationInsightsKey":"YOUR-AI-KEY"} to trace orchestration steps # Check Application Insights → Traces → filter by policy name → verify: # clientActionIntent claim value matches what was passed # Correct step is running / being skipped per the precondition logic
⚠ Common Mistakes and How to Avoid Them

CombinedSignInAndSignUp must not be Order 1 if you add a prior step. B2C historically required CombinedSignInAndSignUp to be the first orchestration step. Adding Step 1 (Direct SignUp) as Order 1 moves Combined to Order 2. The framework handles this correctly when the ClaimsProviderSelections reference a ClaimsExchange that exists in the combined step — but always test that the combined page still works correctly after reordering.

Do not include clientActionIntent in OutputClaims. This claim is internal routing logic. Including it in the RP's OutputClaims section would expose it in the JWT token returned to your application — this is unnecessary and may cause confusion. Keep it in InputClaims only.

AlwaysUseDefaultValue="true" is required. Without it, the OAUTH-KV resolver only populates the claim if the claim bag does not already contain a value for it. Since the claim bag starts empty for each request, this usually works — but AlwaysUseDefaultValue ensures correct behaviour regardless of claim bag state.

Handle the null/absent case in your preconditions. Use a ClaimsExist precondition before a ClaimEquals precondition on the same step. If the claim does not exist (no ?action= parameter was passed), evaluating a ClaimEquals on a non-existent claim can produce unexpected results in some policy versions. The two-precondition guard pattern in Step 1 above is the safe pattern.

Key Takeaways

A single Relying Party policy can serve sign-in, direct sign-up, and forgot password — no need for multiple RP files. The OAUTH-KV claim resolver and orchestration step preconditions do all the branching.
The OAUTH-KV claim resolver {OAUTH-KV:action} reads the ?action= query parameter from the OAuth 2.0 authorization request. It must be declared in InputClaims with AlwaysUseDefaultValue="true" in the RP TechnicalProfile.
The application's "Sign Up" button generates an authorization URL identical to "Sign In" but with &action=signup appended. Both URLs point to the same RP policy file and the same redirect_uri.
Step 1 (Direct Sign-Up) is skipped when clientActionIntent is absent or not equal to signup. Step 2 (Combined) is skipped when objectId is in the claims bag — which happens after Step 1 runs. These two guards together ensure only one path executes per request.
Forgot Password via sub-journey is unaffected by the clientActionIntent branching. It is triggered by the isForgotPassword claim set when the user clicks "Forgot password?" on the combined UI — an independent mechanism.
Use a two-precondition guard on Step 1: first check ClaimsExist, then check ClaimEquals. This prevents unexpected behaviour when the claim is absent and protects against null evaluation errors.
Test both paths using jwt.ms as the redirect URI. Add Application Insights trace logging to verify the claim value and confirm the correct orchestration steps are running and being skipped.
Frequently Asked Questions
Why not just use two separate RP policy files instead?
Two RP files is the alternative approach and is simpler to implement. The problem is policy sprawl — every change to business logic, claims schema, or technical profiles that applies to both flows must be made twice. In a production B2C tenant with compliance requirements, synchronized maintenance across multiple files is error-prone. The single RP with OAUTH-KV branching centralises all identity logic in one policy, which means one file to update, one file to review, and one file to audit. The operational benefit compounds over time as the policy evolves.
Is the ?action=signup parameter secure — can a malicious user modify it to bypass sign-in?
Yes, this parameter is secure for its intended purpose. The ?action=signup parameter only controls which UI screen is shown first. It does not bypass authentication — a user who navigates to the sign-up form still goes through the full registration process and receives a JWT token only after completing all validation steps. A malicious user could append ?action=signup to a sign-in URL, but this would only show them the registration form rather than the sign-in form — not a security bypass. The parameter controls UI flow, not authorization level.
Can I use a different parameter name instead of ?action=signup?
Yes. The parameter name and value are completely under your control. ?action=signup is a convention used in this guide, but you could equally use ?flow=register, ?mode=new-user, or any other convention. Whatever name you use in the URL must match the {OAUTH-KV:name} resolver syntax in the policy, and whatever value you use must match the ClaimEquals precondition value. The claim type name (clientActionIntent) is also just a convention — rename it to anything that makes sense in your policy context.
What if I also want to support social identity providers (Google, Facebook) on the combined page?
The branching logic for the direct sign-up path is independent of social identity provider support on the combined page. Social IdP buttons are configured as ClaimsProviderSelections in the CombinedSignInAndSignUp step (Step 2 in this guide). They continue to work as normal when no ?action=signup parameter is present. For the direct sign-up path (Step 1), you can optionally add a separate step that presents social IdP options during registration, or you can keep the direct sign-up path as local account only. The choice depends on whether your direct sign-up link should support social registration or only email/password registration.
I'm seeing the combined page even when I pass ?action=signup — what is wrong?
The most common causes: (1) AlwaysUseDefaultValue="true" is missing from the InputClaim in the RP file — without it the resolver may not populate the claim consistently. (2) The claim type clientActionIntent is not declared in the ClaimsSchema — if the claim type does not exist, the resolver cannot map to it. (3) The preconditions on Step 1 have ExecuteActionsIf set incorrectly — double-check the logic: you want to skip Step 1 if the claim does not exist (ClaimsExist ExecuteActionsIf="false") and also skip it if the claim exists but is not equal to signup (ClaimEquals ExecuteActionsIf="false"). Use Application Insights trace logging to confirm the claim value is being read correctly before checking precondition logic.

Popular posts from this blog

The Cloud Incumbent: AWS Bedrock Hosts Every Frontier Model and Amazon Is Betting on Neutrality

The Cloud Incumbent: AWS Bedrock Hosts Every Frontier Model and Amazon Is Betting on Neutrality AWS at $37.6 billion quarterly revenue, growing 28%. $13 billion invested in Anthropic. A $100 billion Anthropic-to-AWS commitment. Trainium with $225 billion in customer revenue commitments. The most quietly powerful AI strategy in the race. By Francis Avorgbedor | Azure Engineer  ·  July 4, 2026  ·  14 min read  ·  Amazon · AWS · Cloud AI 74 SEVENAI Momentum Score — Rank #5 $37.6B AWS Q1 2026 revenue — 28% YoY growth ▲ Fastest in 15 quarters $13B Total Amazon investment in Anthropic to date ▲ Strategic anchor 100K+ Customers running Claude on AWS Bedrock ▲ Distribution moat Amazon's AI strategy is built on a thesis that every other Magnificent Seven company is testing against — and that Amazon is uniquely positioned to win regardless of the outcome. The thesis is neutrality. In a race where Microsoft has bet on OpenAI, Google has bet on Gemini, and Meta has bet...

The Importance of Content Marketing in 2026: Building Trust, Driving Leads and Growing Your Business

 The Importance of Content Marketing in 2026: Building Trust, Driving Leads and Growing Your Business Content marketing is not a passing trend – it has become the backbone of modern marketing and sales strategies. Companies that consistently educate and engage their audience with blogs, videos , podcasts and other formats are seeing measurable results in brand awareness, lead generation and revenue. By 2026, content marketing is no longer optional: over 82 % of companies use it and more than 54 % plan to increase their investment . In today’s competitive landscape, high‑quality, customer‑focused content builds trust, attracts qualified prospects and nurtures loyalty throughout the buyer journey. Pervasive adoption and why it matters Widespread usage: Research shows that 73 % of B2B marketers and 70 % of B2C marketers include content marketing in their strategies . Within organisations, dedicated content teams are becoming the norm; 73 % of major o...

How to Reset an Azure Virtual Machine to Factory Settings Using a Managed Disk

How to Reset an Azure Virtual Machine to Factory Settings Using a Managed Disk Azure does not have a single "factory reset" button. What it does have is something better: the OS Disk Swap — a method that swaps out the corrupted or misconfigured OS disk for a clean Windows Server managed disk without deleting the VM, its NICs, its IP addresses, or any attached data disks. Here is how it works, when to use it, and the exact steps to execute it safely. FA Francis Avorgbedor Azure Engineer July 16, 2026 15 min read Azure VMs · Windows Server · Real-World Fix 3 Methods to achieve a clean Windows Server installation on an existing Azure VM ~15min Typical OS Disk Swap duration — VM retains its NICs, IPs, and data disks throughout 0 Data disks affected by an OS Disk Swap — data disks remain attached and untouched 1 Snapshot of the original OS disk you must take before starting — no exceptions Introduction Why Azure Does Not Have a Simple Factory Reset — and What to Do Instead On a ph...
  A slow or unstable internet connection can be incredibly frustrating, but many common issues can be resolved with a bit of troubleshooting. This guide will walk you through a series of steps to diagnose and fix your internet connection. Step 1: Basic Checks & Restarting Your Equipment Often, the simplest solutions are the most effective. Check Cables:  Ensure all cables connected to your modem and router are securely plugged in. This includes the power cables, the Ethernet cable connecting your modem to your router (if you have separate devices), and the cable coming from your internet service provider (ISP) – usually coaxial or fiber optic. Restart Your Modem and Router:  This is the golden rule of internet troubleshooting. Unplug  both your modem and router from their power sources. Wait for at least  30 seconds . This allows the devices to fully power down and clear their temporary ...

Can I Update My Old Computer to Windows 11 — and How Much Will It Cost?

Can I Update My Old Computer to Windows 11 — and How Much Will It Cost? Your i7, 16GB RAM, 512GB SSD machine is powerful enough to run Windows 11 comfortably. The TPM 2.0 and Secure Boot wall is a security checkbox, not a performance ceiling. Here are two proven ways to get past it, what each one costs, and what you are trading away by doing so. $0 Cost of the Windows 11 licence if your existing Windows 10 is genuine — the upgrade remains free in 2026 2 Proven methods to bypass TPM 2.0 and Secure Boot — Rufus (easy) and Registry edit (manual) 25H2 Current Windows 11 version — all known bypass methods tested and confirmed working as of July 2026 Oct 2025 Windows 10 end of life — no more security updates. Staying on Windows 10 now carries real risk. First — Check Your BIOS Before Anything Else You Might Not Actually Need a Bypass Before running any bypass, open your BIOS and look at two settings. Many computers that fail the Windows 11 compatibility check have TPM 2.0 present in the hard...

Azure Files vs Azure NetApp Files: Which One Should You Choose?

Azure Files vs Azure NetApp Files: Which One Should You Choose? Performance tiers, protocol support, dual-protocol capability, pricing models, SAP/Oracle/HPC suitability, data management features, and the decision framework that maps each workload type to the right service — with step-by-step setup procedures for both. FA Francis Avorgbedor Azure Engineer July 15, 2026 20 min read Azure Storage · Architecture 4 Azure Files tiers: Premium SSD, Standard Hot, Cool, Tx Optimized 3 ANF performance tiers: Standard, Premium, Ultra — all SSD-backed 4TiB ANF minimum provisioning — significant cost floor for small workloads Dual ANF serves the same data via SMB and NFS simultaneously — AF cannot Introduction Two Services, One Surface Area — Completely Different Purposes Microsoft offers two fully managed, enterprise-grade file storage services in Azure. They share a surface area — both serve file shares over standard protocols, both run on managed infrastructure, and both integrate with Microsof...
 Digital Marketing Trends and Strategies for SMBs in 2026 Small and mid‑sized businesses (SMBs) are competing in an environment where digital marketing changes faster than ever. The rise of artificial intelligence (AI), voice search and social commerce are reshaping how customers discover, evaluate and purchase products. To succeed, SMBs must understand the trends shaping 2026 and implement strategies that build trust, visibility and conversion—without breaking the budget. AI becomes the backbone of digital marketing AI‑driven personalization is now standard. Advances in machine learning mean even small businesses can personalize messaging at scale. Twilio’s research shows that 92 % of companies use AI‑driven personalization to drive growth . AI tools automate tasks like content creation, segmentation and performance analysis, freeing owners to focus on strategy . AI marketing tools are accessible. According to a U.S. Chamber of Commerce report cited by Thryv, 58...
 Social Media Monetization for Beginners Social media platforms offer numerous avenues for monetization, even for beginners without specialized skills. The key lies in understanding different strategies, creating valuable and authentic content, and consistently engaging with an audience. Here are the primary ways one can monetize social media: • Direct Monetization Methods     ◦ Sponsored Posts and Brand Partnerships: Once you build a decent following, companies will pay you to promote their products or services through your posts, stories, or videos. These often involve a fixed fee per post or campaign and require you to demonstrate influence and an active community. It's crucial to promote products you genuinely like and to be transparent with disclosures about paid partnerships.     ◦ Affiliate Marketing: This involves promoting other companies' products or services using unique links. You earn a commission when someone makes a purchase through your link. Pla...
Creating user profiles for Entra-joined Azure Virtual Desktops (AVD) primarily involves configuring FSLogix Profile Containers . This ensures that user profiles are portable and persistent across sessions, even though the session hosts are Entra-joined. Here's a step-by-step guide: Step 1: Prepare Your Storage for FSLogix Profiles You'll need a file share that can be accessed by your AVD session hosts and where user profile disks will be stored. Azure Files is a common and recommended solution for this. Create an Azure Storage Account : Go to the Azure portal, search for "Storage accounts," and click "Create." Choose your subscription and resource group. Give it a unique name (e.g., avdprofilesstorage). Select a region. For performance, consider "Premium" with "File shares" as the account kind, or "Standard" with "ZRS" or "GRS"...
Building Online Presence : A Skill-Free Income Guide Building a strong online presence is fundamental for generating income without prior skills, and it involves several key strategies, from mindset to practical execution. Foundational Mindset Shifts for Success Developing the right mindset is the starting point for building an online presence, influencing your motivation and ability to overcome challenges. • Embrace Learning and Adaptability Your ability to succeed online without specific skills starts with believing that change is possible and that you can learn as you go. The digital world changes rapidly, so being open to trying new methods and adapting your approach is crucial to keep moving forward. • Persistence Over Perfection View setbacks as opportunities to learn rather than failures, which helps build resilience. Recognize that success comes from persistence, not perfection. Small, consistent wins build confidence. • Focus on What You Control Concentrate on your effort, att...