Identityserver4: ID4 exceeds Url length limit of microsoft when using "personal account"

Created on 3 Dec 2020  路  3Comments  路  Source: IdentityServer/IdentityServer4

Dear,

When i login using a microsoft-workAccount there are no issues.
When i login with a microsoft-personalAccount the state seems to exceed the max string limit of Microsoft.

To reduce the length of the URL i call the AddOidcStateDataFormatterCache extension method: AddOidcStateDataFormatterCache()

As suggested in the docs

This did not reduce the length, did nothing at all... anything i could've missed? The docs say _"simply call the AddOidcStateDataFormatterCache extension method"_

Some context:
```C#
private static void AddExternalProviders(AuthenticationBuilder authenticationBuilder,
IConfiguration configuration, IHostingEnvironment hostingEnvironment)
{
var externalProviderConfiguration = configuration.GetSection(nameof(ExternalProvidersConfiguration)).Get();

        // Only enable Github in development environment
        if (hostingEnvironment.IsDevelopment() && externalProviderConfiguration.UseGitHubProvider)
        {
            authenticationBuilder.AddGitHub(options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                options.ClientId = externalProviderConfiguration.GitHubClientId;
                options.ClientSecret = externalProviderConfiguration.GitHubClientSecret;
                options.Scope.Add("user:email");
            });
        }

        if (externalProviderConfiguration.UseGoogleProvider)
        {
            authenticationBuilder.AddGoogle(options =>
            {
                // When using external authentication with ASP.NET Core Identity, the SignInScheme must be set to "Identity.External" 
                // instead of IdentityServerConstants.ExternalCookieAuthenticationScheme
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; // "Identity.External";
                options.ClientId = externalProviderConfiguration.GoogleClientId;
                options.ClientSecret = externalProviderConfiguration.GoogleClientSecret;
                options.ClaimActions.MapJsonKey("urn:google:picture", "picture", "url");
                options.ClaimActions.MapJsonKey("urn:google:locale", "locale", "string");
            });
        }

        if (externalProviderConfiguration.UseMicrosoftProvider)
        {
            authenticationBuilder.AddMicrosoftAccount(options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                options.ClientId = externalProviderConfiguration.MicrosoftClientId;
                options.ClientSecret = externalProviderConfiguration.MicrosoftClientSecret;
            });
        }
    }

```C#
  public void ConfigureServices(IServiceCollection services)
        {
            services.ConfigureRootConfiguration(Configuration);

            services.AddStackExchangeRedisCache(setup =>
            {
                setup.Configuration = Configuration.GetSection(nameof(RedisServerConfiguration)).Get<RedisServerConfiguration>().Server;
            });

            // configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
            services.AddOidcStateDataFormatterCache();

            // Add DbContext for Asp.Net Core Identity
            services.AddIdentityDbContext<AdminIdentityDbContext>(Configuration, Environment);
            // Add DbContext and Services for Tenant Configuration
            services.AddTenantConfiguration<TenantConfigurationDbContext>(Configuration);
            // Add email senders which is currently setup for SendGrid and SMTP
            services.AddEmailSenders(Configuration);

            // Add services for authentication, including Identity model, IdentityServer4 and external providers
            services.AddAuthenticationServices<IdentityServerConfigurationDbContext, IdentityServerPersistedGrantDbContext, AdminIdentityDbContext, UserIdentity, UserIdentityRole>(Environment, Configuration, Logger);

            // Add all dependencies for Asp.Net Core Identity in MVC - these dependencies are injected into generic Controllers
            // Including settings for MVC and Localization
            // If you want to change primary keys or use another db model for Asp.Net Core Identity:
            services.AddMvcWithLocalization<UserIdentity, string>();

            // Add authorization policies for MVC
            services.AddAuthorizationPolicies();
            services.AddScoped<IProfileService, ProfileService>();
        }
question

All 3 comments

Odd, I just tested it and it worked. Are you testing with our sample code?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Questions are community supported only and the authors/maintainers may or may not have time to reply. If you or your company would like commercial support, please see here for more information.

Because we do not use "AddOpenIdConnect()" but AddMicrosoft()

I guess this doesn't implement the -> ISecureDataFormat<AuthenticationProperties>

So i add a custom implementation:

_ConfigureMicrosoftOptions.cs_
```C#
internal class ConfigureMicrosoftOptions : IPostConfigureOptions
{
private readonly string[] _schemes;
private readonly IHttpContextAccessor _httpContextAccessor;

    public ConfigureMicrosoftOptions(string[] schemes, IHttpContextAccessor httpContextAccessor)
    {
        _schemes = schemes ?? throw new ArgumentNullException(nameof(schemes));
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }

    public void PostConfigure(string name, MicrosoftAccountOptions options)
    {
        // no schemes means configure them all
        if (_schemes.Length == 0 || _schemes.Contains(name))
        {
            options.StateDataFormat = new DistributedCacheStateDataFormatter(_httpContextAccessor, name);
        }
    }
}

_part of StartupHelpers.cs_
```C#
public static IServiceCollection AddMicrosoftStateDataFormatterCache(this IServiceCollection services, params string[] schemes)
{
    services.AddSingleton<IPostConfigureOptions<MicrosoftAccountOptions>>(
        svcs => new ConfigureMicrosoftOptions(
            schemes,
            svcs.GetRequiredService<IHttpContextAccessor>()));
    return services;
}

_ConfigureServices @ Startup.cs_
```C#
// configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
services.AddOidcStateDataFormatterCache();
services.AddMicrosoftStateDataFormatterCache();

```
This fixed the issue ! @brockallen

Was this page helpful?
0 / 5 - 0 ratings

Related issues

klioqc picture klioqc  路  3Comments

osmankibar picture osmankibar  路  3Comments

user1336 picture user1336  路  3Comments

leastprivilege picture leastprivilege  路  3Comments

eshorgan picture eshorgan  路  3Comments