Tengo una instancia de IdentityServer4 que intento ejecutar en un contenedor Docker detrás de un proxy nginx. Lo he basado en la muestra de identidad AspNet del repositorio de Git, pero después de que un usuario registra con éxito una nueva cuenta, aparece "Se produjo un error" de IdentityServer y los registros muestran

[07:46:39 ERR] An unhandled exception has occurred: sub claim is missing System.InvalidOperationException: sub claim is missing at IdentityServer4.IdentityServerPrincipal.AssertRequiredClaims(ClaimsPrincipal principal at IdentityServer4.Hosting.IdentityServerAuthenticationService.AugmentPrincipal(ClaimsPrincipal principal at IdentityServer4.Hosting.IdentityServerAuthenticationService.<SignInAsync>d__7.MoveNext

Mi Startup.cs se ve así

var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().
var connectionString = Configuration.GetConnectionString("DefaultConnection");
var issuerUri = Configuration.GetSection("IssuerUri").Value;

services.AddDbContext<ApplicationDbContext>(options => 
    options.UseSqlServer(connectionString));

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

services.AddTransient<IEmailSender, EmailSender>();

services.AddMvc();

services.AddCors(o => o.AddPolicy("CorsPolicy", b =>
{
    b.AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader();
}));

services.AddIdentityServer(options =>
{
    options.IssuerUri = issuerUri;
    options.PublicOrigin = issuerUri;
})
.AddDeveloperSigningCredential()

// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
    options.ConfigureDbContext = builder =>
        builder.UseSqlServer(connectionString,
            sql => sql.MigrationsAssembly(migrationsAssembly));
})

// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
    options.ConfigureDbContext = builder =>
        builder.UseSqlServer(connectionString,
            sql => sql.MigrationsAssembly(migrationsAssembly));

    // this enables automatic token cleanup. this is optional.
    //options.EnableTokenCleanup = true;
    //options.TokenCleanupInterval = 30;
});

Debo haber perdido alguna configuración obvia, pero no puedo ver dónde. ¿Algunas ideas?

ACTUALIZACIÓN He progresado un poco con esto y parecía haber pasado el error inicial. El usuario ahora está autenticado pero la página signin-oidc arroja el error

[11:33:21 INF] Request starting HTTP/1.1 POST http://mvcportal.co.uk/signin-oidc application/x-www-form-urlencoded 1565
[11:33:21 INF] AuthenticationScheme: Cookies signed in.
[11:33:21 INF] Request finished in 684.8425ms 302
[11:33:27 INF] Request starting HTTP/1.1 POST http://mvcportal.co.uk/signin-oidc application/x-www-form-urlencoded 1565
[11:33:27 ERR] Message contains error: 'invalid_grant', error_description: 'error_description is null', error_uri: 'error_uri is null', status code '400'.

Tengo un JWT válido pero noto que el idp no es igual al emisor. ¿Es eso correcto?

{
  "nbf": 1508758474,
  "exp": 1508758774,
  "iss": "http://myproxiedlogonsitebehindnginx.co.uk",
  "aud": "mvc.portal",
  "nonce": "636443552746808541.MGVjMzk2NTEtYmYwNS00NmQwLTllOTQtZDVjNjdlYTA2YWVlYTQ3Zjg1NjgtZDA1Yi00NDE0LWJiYmYtMjM4YzI1NjZlYTcx",
  "iat": 1508758474,
  "c_hash": "kG7wG8vSgRe5zdriHQ6iMA",
  "sid": "c9410ee8f27b69c32e43d5ac3d407f37",
  "sub": "e80fb854-cab2-4381-8057-19de0fea73f4",
  "auth_time": 1508757008,
  "idp": "local",
  "amr": [
    "pwd"
  ]
}

ACTUALIZACIÓN 2 Esta es la configuración del cliente en idsrv si eso ayuda

new Client
{
    ClientId = "mvc.portal",
    ClientName = "Customer Portal",
    ClientUri = customerPortalBaseUri,

    ClientSecrets =
    {
        new Secret("21f51463-f436-4a84-92ce-1b520dd63a81".Sha256())
    },

    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    AllowAccessTokensViaBrowser = false,

    RedirectUris = { $"{customerPortalBaseUri}/signin-oidc"},
    FrontChannelLogoutUri = $"{customerPortalBaseUri}/signout-oidc",
    PostLogoutRedirectUris = { $"{customerPortalBaseUri}/signout-callback-oidc" },

    AllowOfflineAccess = true,

    RequireConsent = false,

    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.Email
    }
}

Y esta es la configuración del cliente / portal

services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = "oidc";
    })
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddOpenIdConnect("oidc", options =>
    {
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.Authority = "http://myproxiedlogonsitebehindnginx.co.uk";
        options.RequireHttpsMetadata = false;
        options.ClientId = "mvc.portal";
        options.ClientSecret = "21f51463-f436-4a84-92ce-1b520dd63a81";
        options.ResponseType = "code id_token";
        options.SaveTokens = true;
        options.GetClaimsFromUserInfoEndpoint = true;
    });

ACTUALIZACIÓN 3 Así que ahora estoy convencido de que tiene algo que ver con la implementación, porque si ejecuto la aplicación mvc en mi máquina local pero uso el idsvr implementado en el contenedor (detrás de nginx), puedo autenticar sin problemas, sin embargo, si intento versión del portal contenedorizado todavía obtengo un 500 no manejado sin que sea registrado y luego, si reintento la acción, obtengo esto registrado:

[11:22:51 INF] Request starting HTTP/1.1 POST http://mvcportal.co.uk/signin-oidc application/x-www-form-urlencoded 1559
[11:22:51 ERR] Message contains error: 'invalid_grant', error_description: 'error_description is null', error_uri: 'error_uri is null', status code '400'.
[11:22:51 ERR] Exception occurred while processing message.
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_grant'], error_description: 'error_description is null', error_uri: 'error_uri is null'.
5
Dan Kennedy 23 oct. 2017 a las 11:05

3 respuestas

La mejor respuesta

Así que finalmente llegué al fondo. Parece que los límites de encabezado predeterminados en nginx no funcionan bien y encontré esto en los registros upstream sent too big header while reading response header from upstream

Actualización de la configuración de nginx para incluir las líneas

proxy_buffer_size          128k;
proxy_buffers              4 256k;
proxy_busy_buffers_size    256k;

Evitó el error 502 y todo se autentica bien ahora.

3
Dan Kennedy 31 oct. 2017 a las 14:14

Gracias por la respuesta Estimado Dan: Además, recibí este error y he resuelto este problema de esta manera.

Encuentre esta línea en Startup.cs confgiureservices

services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores()
.AddIdentityServer()
.AddDefaultTokenProviders();

Asegúrese de que .AddIdentityServer() esté allí.

0
Metin Atalay 6 sep. 2018 a las 06:26

Estaba teniendo el mismo problema exacto y lo resolví agregando:

.AddAspNetIdentity<ApplicationUser>();

Para

services.AddIdentityServer()

En Startup.cs

0
Amirhossein Yari 21 mar. 2020 a las 23:53