IdentityServer / IdentityServer4

OpenID Connect and OAuth 2.0 Framework for ASP.NET Core
https://identityserver.io
Apache License 2.0
9.23k stars 4.02k forks source link

ID4 exceeds Url length limit of microsoft when using "personal account" #5061

Closed TLA020 closed 3 years ago

TLA020 commented 3 years ago

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:

  private static void AddExternalProviders(AuthenticationBuilder authenticationBuilder,
            IConfiguration configuration, IHostingEnvironment hostingEnvironment)
        {
            var externalProviderConfiguration = configuration.GetSection(nameof(ExternalProvidersConfiguration)).Get<ExternalProvidersConfiguration>();

            // 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;
                });
            }
        }
  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>();
        }
brockallen commented 3 years ago

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

stale[bot] commented 3 years ago

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.

TLA020 commented 3 years ago

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

internal class ConfigureMicrosoftOptions : IPostConfigureOptions<MicrosoftAccountOptions>
    {
        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

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

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

This fixed the issue ! @brockallen

stale[bot] commented 3 years ago

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.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.