Autenticación JWT y Swagger con .Net core 3.0

10

Estoy desarrollando una API web con .Net core 3.0 y quiero integrarla con SwashBuckle.Swagger. Está funcionando bien, pero cuando agrego autenticación JWT, no funciona como esperaba. Para hacer eso, agregué el siguiente código:

  services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My Web API", Version = "v1" });
            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey
            });

        });

Después de agregar AddSecurityDefinition función, puedo ver el botón Autorizar y cuando hago clic en él, veo el siguiente formulario: ingrese la descripción de la imagen aquí

Luego escribo Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjh, después de hacerlo, espero ver authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjhen el encabezado de la solicitud, cuando envío una solicitud a la API web de Swagger. Pero la autorización no se agrega al encabezado de la solicitud. Estoy usando SwashBuckle.Swagger (5.0.0-rc3). Tenga en cuenta que hay muchas muestras que funcionan bien en .net core 2.0, pero las funciones Swagbuckle swagger han cambiado en la última versión, por lo que no puedo usar esas muestras.

Mehrdad Babaki
fuente
En el enlace que mencionaste no hay respuesta. Además .net core 3.0 es ligeramente diferente.
Mehrdad Babaki
La respuesta es agregar .AddSecurityRequirement(globalmente) o .Security(en el nivel de operación), como se explica en las respuestas a la pregunta vinculada. AddSecurityDefinitionsolo no es suficiente.
Helen
Agregué pero nada cambió. Creo que es por eso que no se selecciona como respuesta.
Mehrdad Babaki, el
Respondí esto recientemente en otra pregunta, eche un vistazo aquí: stackoverflow.com/a/57872872/3952573
Pavlos

Respuestas:

33

Después de un poco de investigación, finalmente encontré la respuesta aquí

Antes de ver esta página, sabía que debería usar AddSecurityRequirementdespuésAddSecurityDefinition debido a muchas muestras, pero era un problema que los parámetros de la función hayan cambiado en .NET Core 3.0.

Por cierto, la respuesta final es la siguiente:

services.AddSwaggerGen(c =>
{
  c.SwaggerDoc("v1", new OpenApiInfo { 
    Title = "My API", 
    Version = "v1" 
  });
  c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
    In = ParameterLocation.Header, 
    Description = "Please insert JWT with Bearer into field",
    Name = "Authorization",
    Type = SecuritySchemeType.ApiKey 
  });
  c.AddSecurityRequirement(new OpenApiSecurityRequirement {
   { 
     new OpenApiSecurityScheme 
     { 
       Reference = new OpenApiReference 
       { 
         Type = ReferenceType.SecurityScheme,
         Id = "Bearer" 
       } 
      },
      new string[] { } 
    } 
  });
});
Mehrdad Babaki
fuente
Muchas gracias, funciona bien conmigo
Anas Al-Qudah
2
Esto funcionó. Consejo: no olvides escribir "Bearer" antes del token real. Y es un poco molesto que la arrogancia siempre diga autorizado, no importa lo que escriba en el cuadro de texto ... ¡Gracias!
CodeHacker
Esto funciona en net core 3 y swagger
ericpap
Quien salva una vida salva al mundo. Me salvaste la vida ;-) gracias
Vahid Farahmandian
6

Si está utilizando Swagger 3.0, entonces tiene soporte incorporado para la autenticación JWT.

Debe usar ParameterLocation.Header, SecuritySchemeType.Http, bearer y JWT en OpenApiSecurityScheme como se muestra a continuación.

Después de esto, no necesitaría especificar el token en formato Bearer {token} . Solo especifique el token y el esquema de seguridad lo aplicará automáticamente en el encabezado.

// Bearer token authentication
OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme()
{
    Name = "Bearer",
    BearerFormat = "JWT",
    Scheme = "bearer",
    Description = "Specify the authorization token.",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.Http,
};
c.AddSecurityDefinition("jwt_auth", securityDefinition);

// Make sure swagger UI requires a Bearer token specified
OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme()
{
    Reference = new OpenApiReference()
    {
        Id = "jwt_auth",
        Type = ReferenceType.SecurityScheme
    }
};
OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement()
{
    {securityScheme, new string[] { }},
};
c.AddSecurityRequirement(securityRequirements);

ingrese la descripción de la imagen aquí

ameya
fuente
¡Gracias! Después de muchas publicaciones que no funcionaron para mí, ¡este método sí!
Matt Casto
2

Si no desea agregar un token manualmente y desea que los ámbitos sean seleccionables junto con pasar un ID de cliente al servidor de identidad, puede agregar algo como esto.

He usado flujo implícito, pero puedes configurar cualquier flujo usando el siguiente mecanismo:

options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme()
{
  Flows = new OpenApiOAuthFlows
  {
    Implicit = new OpenApiOAuthFlow
    {                            
      AuthorizationUrl = new Uri("http://localhost"),
      TokenUrl = new Uri("http://localhost"),
      Scopes = new Dictionary<string, string>
      {
        { "Foundation API", "FoundationApi" }
      }
    }
  },
  In = ParameterLocation.Header,                    
  Name = "Authorization",
  Type = SecuritySchemeType.OAuth2                    
});

La salida será así:

ingrese la descripción de la imagen aquí

Prabhanjan Kumar Mahapatra
fuente
1

Aquí hay una solución actualizada para Swashbuckle.AspNetCore 5.3.2, integrada con IdentityServer4, con una API asegurada con un token Bearer.

En ConfigureServices()método:

        services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
            options.AddSecurityDefinition("Bearer", SecuritySchemes.BearerScheme(Configuration));
            options.AddSecurityRequirement(new OpenApiSecurityRequirement()
            {
                { SecuritySchemes.OAuthScheme, new List<string>() }
            });
        });

En Configure()método:

        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint("/My.Api/swagger/v1/swagger.json", "My API V1");
            options.OAuthClientId(Clients.TestClient);
            options.OAuthAppName("My Api - Swagger");
            options.OAuthClientSecret(Configuration["TestClientSecret"]);
        });

internal static class SecuritySchemes
{
    public static OpenApiSecurityScheme BearerScheme(IConfiguration config) => new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Description = "Standard authorisation using the Bearer scheme. Example: \"bearer {token}\"",
        In = ParameterLocation.Header,
        Name = "Authorization",
        Scheme = "Bearer",
        OpenIdConnectUrl = new System.Uri($"{config["TokenServerUrl"]}.well-known/openid-configuration"),
        BearerFormat = "JWT",
        Flows = new OpenApiOAuthFlows
        {
            Password = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new System.Uri($"{config["TokenServerUrl"]}connect/authorize"),
                Scopes = new Dictionary<string, string>
                    {
                        { Scopes.Api, "My Api" }
                    },
                TokenUrl = new System.Uri($"{config["TokenServerUrl"]}connect/token")
            }
        }
    };

    public static OpenApiSecurityScheme OAuthScheme => new OpenApiSecurityScheme
    {
        Reference = new OpenApiReference
        {
            Type = ReferenceType.SecurityScheme,
            Id = "Bearer"
        },
        Scheme = "oauth2",
        Name = "Bearer",
        In = ParameterLocation.Header,

    };
}
Paul Taylor
fuente
Este es un salvavidas. También funciona para flujo implícito donde cambié Contraseña a Implícito en la configuración de Flujos. ¡Muchas gracias!
Larsbj
0

Si alguien está usando NSwag y ha aterrizado aquí después de buscar la solución, aquí está el enlace de la documentación oficial.

NSwag Habilitar autenticación JWT

PD: Sé que la pregunta original era para SwashBuckle, pero Google también muestra este enlace primero cuando busca NSwag.

Prateek Kumar Dalbehera
fuente