Skip to content

Latest commit

 

History

History
525 lines (412 loc) · 14.1 KB

File metadata and controls

525 lines (412 loc) · 14.1 KB

Migration Guide: Authority vs Instance/TenantId Configuration

This guide helps you upgrade existing Microsoft.Identity.Web applications to use recommended authority configuration patterns, especially if your app throws an InvalidOperationException about conflicting Authority and Instance/TenantId settings.

Understanding the Error

If your application fails to start with an error like this:

System.InvalidOperationException: [MsIdWeb] Both 'Authority' ('https://login.microsoftonline.com/common')
and 'Instance'/'TenantId' ('https://login.microsoftonline.com/', 'organizations') are configured.
These settings conflict. Remove either 'Authority' or 'Instance'/'TenantId' from the configuration.

This means your configuration has conflicting authority settings. The library no longer silently ignores one of the values -- it throws at startup to surface the conflict.

Quick Fix Options

Option 1: Remove Authority (Recommended for most scenarios)

Before (throws InvalidOperationException):

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/common",
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "organizations",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

After:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "organizations",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Option 2: Remove Instance and TenantId (Simpler for some scenarios)

Before (throws InvalidOperationException):

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/common",
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "common",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

After:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/common",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Scenario-Specific Migration Patterns

Azure AD Single-Tenant Applications

Pattern 1: From Authority to Instance/TenantId

Before (using Authority):

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/12345678-1234-1234-1234-123456789012",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

After (split into Instance/TenantId - Recommended):

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "12345678-1234-1234-1234-123456789012",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Benefits:

  • Clear separation of instance and tenant
  • Easier to update for different environments
  • Consistent with Microsoft documentation

Pattern 2: Keep Authority (Not Recommended for AAD)

Warning: For AAD authorities, using Authority alone routes through MSAL's generic OIDC path (WithOidcAuthority), which skips AAD-specific security and resilience features. Prefer Instance + TenantId (Pattern 1).

If you still prefer the Authority format:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/12345678-1234-1234-1234-123456789012",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Note: The library routes this through MSAL's WithOidcAuthority() path, so AAD-specific optimizations do not apply. For AAD scenarios, always prefer Instance + TenantId.

Azure AD Multi-Tenant Applications

From Mixed Configuration

Before (throws InvalidOperationException):

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/organizations",
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "common",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

After (using Instance/TenantId):

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "organizations",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Alternative (using Authority -- not recommended for AAD):

Warning: Using Authority alone for AAD routes through MSAL's generic OIDC path, losing AAD-specific security and resilience features.

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/organizations",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Azure AD B2C Applications

For B2C, always use Authority including the policy path. Do NOT use Instance/TenantId separately.

Consolidate to Authority-Only

Before (throws InvalidOperationException):

{
  "AzureAdB2C": {
    "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_susi",
    "Instance": "https://contoso.b2clogin.com/",
    "TenantId": "contoso.onmicrosoft.com",
    "ClientId": "11111111-1111-1111-1111-111111111111",
    "Domain": "contoso.onmicrosoft.com"
  }
}

After (correct Authority-based configuration):

{
  "AzureAdB2C": {
    "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_susi",
    "ClientId": "11111111-1111-1111-1111-111111111111",
    "Domain": "contoso.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_susi"
  }
}

Critical: B2C requires the policy path in the Authority. Splitting into Instance/TenantId loses the policy information.

CIAM Applications

For CIAM, use the complete Authority URL. The library handles CIAM authorities automatically.

Remove Conflicting Properties

Before (throws InvalidOperationException):

{
  "AzureAd": {
    "Authority": "https://contoso.ciamlogin.com/contoso.onmicrosoft.com",
    "Instance": "https://contoso.ciamlogin.com/",
    "TenantId": "contoso.onmicrosoft.com",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

After (correct CIAM configuration):

{
  "AzureAd": {
    "Authority": "https://contoso.ciamlogin.com/contoso.onmicrosoft.com",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Custom Domain CIAM

Before:

{
  "AzureAd": {
    "Authority": "https://login.contoso.com/contoso.onmicrosoft.com",
    "Instance": "https://login.contoso.com/",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

After:

{
  "AzureAd": {
    "Authority": "https://login.contoso.com/contoso.onmicrosoft.com",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Note: Ensure your custom domain is properly configured in your CIAM tenant before using it in your application.

Government Cloud Migrations

Azure Government (US)

Before (throws InvalidOperationException):

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.us/12345678-1234-1234-1234-123456789012",
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "12345678-1234-1234-1234-123456789012",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

After (corrected):

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.us/",
    "TenantId": "12345678-1234-1234-1234-123456789012",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Azure China

After (using Instance/TenantId):

{
  "AzureAd": {
    "Instance": "https://login.chinacloudapi.cn/",
    "TenantId": "12345678-1234-1234-1234-123456789012",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Alternative (using Authority -- not recommended for AAD):

Warning: Using Authority alone for AAD routes through MSAL's generic OIDC path, losing AAD-specific security and resilience features.

{
  "AzureAd": {
    "Authority": "https://login.chinacloudapi.cn/12345678-1234-1234-1234-123456789012",
    "ClientId": "11111111-1111-1111-1111-111111111111"
  }
}

Multi-Environment Configuration Strategy

Using Environment-Specific Files

Instead of maintaining different configurations in code, use environment-specific settings files:

appsettings.json (base configuration)

{
  "AzureAd": {
    "ClientId": "11111111-1111-1111-1111-111111111111",
    "CallbackPath": "/signin-oidc"
  }
}

appsettings.Development.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "common"
  }
}

appsettings.Production.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "12345678-1234-1234-1234-123456789012"
  }
}

Using Azure Key Vault for Authority Settings

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Load configuration from Key Vault
if (builder.Environment.IsProduction())
{
    var keyVaultEndpoint = new Uri(builder.Configuration["KeyVaultEndpoint"]!);
    builder.Configuration.AddAzureKeyVault(
        keyVaultEndpoint,
        new DefaultAzureCredential());
}

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));

Key Vault Secrets:

  • AzureAd--Instance: https://login.microsoftonline.com/
  • AzureAd--TenantId: 12345678-1234-1234-1234-123456789012
  • AzureAd--ClientId: 11111111-1111-1111-1111-111111111111
  • AzureAd--ClientSecret: your-client-secret

Code-Based Configuration Migration

Before: Mixed Configuration in Code (Throws InvalidOperationException)

// Startup.cs or Program.cs (old pattern)
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        options.Authority = "https://login.microsoftonline.com/common";
        options.Instance = "https://login.microsoftonline.com/";
        options.TenantId = "organizations";
        options.ClientId = "11111111-1111-1111-1111-111111111111";
    });

After: Consistent Configuration

Option 1: Using Instance/TenantId:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        options.Instance = "https://login.microsoftonline.com/";
        options.TenantId = "organizations";
        options.ClientId = "11111111-1111-1111-1111-111111111111";
    });

Option 2: Using Authority:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        options.Authority = "https://login.microsoftonline.com/organizations";
        options.ClientId = "11111111-1111-1111-1111-111111111111";
    });

Option 3: Using Configuration Section (Recommended):

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));

Testing Your Migration

Step 1: Update Configuration

Choose your preferred pattern and update appsettings.json accordingly.

Step 2: Verify Startup

After updating your configuration, restart your application and verify that it starts without InvalidOperationException.

Step 3: Verify Authentication Flow

  1. Navigate to a protected page in your application
  2. Verify you're redirected to the correct sign-in page
  3. Sign in and verify successful authentication
  4. Check that tokens are acquired correctly

Step 4: Monitor Logs

Enable detailed logging to verify the configuration is applied correctly:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.Identity.Web": "Debug"
    }
  }
}

Look for log entries confirming your authority configuration without errors.

Common Migration Issues

Issue 1: Sign-in Redirect to Wrong Tenant

Symptom: Users are redirected to an unexpected tenant for authentication.

Cause: Instance or TenantId values don't match the intended authority.

Solution: Verify that Instance and TenantId, when combined, equal your intended Authority URL.

Issue 2: Configuration Not Taking Effect

Symptom: Changes to configuration don't seem to apply.

Cause: Configuration caching or environment-specific overrides.

Solution:

  • Restart the application
  • Check for environment-specific settings files that might override your changes
  • Verify configuration binding in code

Issue 3: B2C Policy Not Found

Symptom: "AADB2C90008: The provided grant has not been issued for this endpoint"

Cause: Policy path missing from Authority after migration.

Solution: Ensure the B2C Authority includes the full policy path:

{
  "AzureAdB2C": {
    "Authority": "https://contoso.b2clogin.com/contoso.onmicrosoft.com/B2C_1_susi",
    "ClientId": "..."
  }
}

Issue 4: CIAM Custom Domain Errors

Symptom: Authentication fails with custom domain.

Cause: Mixing Authority with Instance/TenantId (throws InvalidOperationException) or custom domain not configured properly in Azure.

Solution: Use Authority only and verify custom domain configuration:

{
  "AzureAd": {
    "Authority": "https://login.contoso.com/contoso.onmicrosoft.com",
    "ClientId": "..."
  }
}

Ensure your custom domain is properly configured in the Azure portal.

Rollback Plan

If migration causes issues, you can temporarily revert while investigating:

Quick Rollback

  1. Restore your previous appsettings.json from version control
  2. Restart the application
  3. Verify authentication works with the old configuration

Gradual Migration

If you have multiple applications:

  1. Migrate one application first
  2. Test thoroughly in non-production environments
  3. Monitor for issues before migrating additional applications
  4. Use feature flags if available to toggle between configurations

Additional Resources

Getting Help

If you encounter issues during migration:

  1. Check the FAQ for common questions
  2. Enable debug logging to gather diagnostic information
  3. Review the GitHub Issues for similar problems
  4. Open a new issue with detailed configuration (sanitize sensitive values) and log output