JWT-Authentifizierung für die ASP.NET-Web-API

264

Ich versuche, das JWT-Inhaber-Token (JSON Web Token) in meiner Web-API-Anwendung zu unterstützen, und verliere mich.

Ich sehe Unterstützung für .NET Core und für OWIN-Anwendungen.
Ich hoste derzeit meine Anwendung in IIS.

Wie kann ich dieses Authentifizierungsmodul in meiner Anwendung erreichen? Gibt es eine Möglichkeit, die <authentication>Konfiguration ähnlich wie bei der Verwendung von Formularen / Windows-Authentifizierung zu verwenden?

Amir Popovich
quelle

Antworten:

611

Ich habe diese Frage beantwortet: So sichern Sie eine ASP.NET-Web-API vor 4 Jahren mit HMAC.

Jetzt haben sich viele Dinge in Bezug auf die Sicherheit geändert, insbesondere JWT wird immer beliebter. Hier werde ich versuchen zu erklären, wie man JWT so einfach und grundlegend wie möglich verwendet, damit wir uns nicht aus dem Dschungel von OWIN, Oauth2, ASP.NET Identity ... :) verlieren.

Wenn Sie das JWT-Token nicht kennen, müssen Sie sich Folgendes genauer ansehen:

https://tools.ietf.org/html/rfc7519

Grundsätzlich sieht ein JWT-Token folgendermaßen aus:

<base64-encoded header>.<base64-encoded claims>.<base64-encoded signature>

Beispiel:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImN1b25nIiwibmJmIjoxNDc3NTY1NzI0LCJleHAiOjE0Nzc1NjY5MjQsImlhdCI6MTQ3NzU2NTcyNH0.6MzD1VwA5AcOcajkFyKhLYybr3h13iZjDyHm9zysDFQ

Ein JWT-Token besteht aus drei Abschnitten:

  1. Header: JSON-Format, das in Base64 codiert ist
  2. Ansprüche: JSON-Format, das in Base64 codiert ist.
  3. Signatur: Erstellt und signiert basierend auf Header und Ansprüchen, die in Base64 codiert sind.

Wenn Sie die Website jwt.io mit dem obigen Token verwenden, können Sie das Token dekodieren und wie folgt anzeigen :

Geben Sie hier die Bildbeschreibung ein

Technisch gesehen verwendet JWT eine Signatur, die von Headern und Ansprüchen mit dem in den Headern angegebenen Sicherheitsalgorithmus signiert ist (Beispiel: HMACSHA256). Daher muss JWT über HTTPs übertragen werden, wenn Sie vertrauliche Informationen in Ansprüchen speichern.

Um die JWT-Authentifizierung verwenden zu können, benötigen Sie keine OWIN-Middleware, wenn Sie über ein älteres Web-API-System verfügen. Das einfache Konzept besteht darin, ein JWT-Token bereitzustellen und das Token zu validieren, wenn die Anforderung eingeht. Das ist es.

Zurück zur Demo, um JWT-Token leicht zu halten, speichere ich nur usernameund expiration timein JWT. Auf diese Weise müssen Sie jedoch eine neue lokale Identität (Principal) neu erstellen, um weitere Informationen hinzuzufügen, z. B.: Rollen .., wenn Sie eine Rollenautorisierung durchführen möchten. Wenn Sie jedoch weitere Informationen zu JWT hinzufügen möchten, liegt es an Ihnen: Es ist sehr flexibel.

Anstatt die OWIN-Middleware zu verwenden, können Sie einfach einen JWT-Token-Endpunkt bereitstellen, indem Sie die Aktion des Controllers verwenden:

public class TokenController : ApiController
{
    // This is naive endpoint for demo, it should use Basic authentication
    // to provide token or POST request
    [AllowAnonymous]
    public string Get(string username, string password)
    {
        if (CheckUser(username, password))
        {
            return JwtManager.GenerateToken(username);
        }

        throw new HttpResponseException(HttpStatusCode.Unauthorized);
    }

    public bool CheckUser(string username, string password)
    {
        // should check in the database
        return true;
    }
}

Dies ist eine naive Handlung; In der Produktion sollten Sie eine POST-Anforderung oder einen Basisauthentifizierungsendpunkt verwenden, um das JWT-Token bereitzustellen.

Wie wird das Token basierend auf generiert username?

Sie können das System.IdentityModel.Tokens.Jwtvon Microsoft aufgerufene NuGet-Paket verwenden , um das Token zu generieren, oder sogar ein anderes Paket, wenn Sie möchten. In der Demo verwende ich HMACSHA256mit SymmetricKey:

/// <summary>
/// Use the below code to generate symmetric Secret Key
///     var hmac = new HMACSHA256();
///     var key = Convert.ToBase64String(hmac.Key);
/// </summary>
private const string Secret = "db3OIsj+BXE9NZDy0t8W3TcNekrF+2d/1sFnWG4HnV8TZY30iTOdtVWJG8abWvB1GlOgJuQZdcF2Luqm/hccMw==";

public static string GenerateToken(string username, int expireMinutes = 20)
{
    var symmetricKey = Convert.FromBase64String(Secret);
    var tokenHandler = new JwtSecurityTokenHandler();

    var now = DateTime.UtcNow;
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.Name, username)
        }),

        Expires = now.AddMinutes(Convert.ToInt32(expireMinutes)),

        SigningCredentials = new SigningCredentials(
            new SymmetricSecurityKey(symmetricKey), 
            SecurityAlgorithms.HmacSha256Signature)
    };

    var stoken = tokenHandler.CreateToken(tokenDescriptor);
    var token = tokenHandler.WriteToken(stoken);

    return token;
}

Der Endpunkt für die Bereitstellung des JWT-Tokens ist fertig. Wie kann nun die JWT validiert werden, wenn die Anfrage eingeht? In der Demo habe ich gebaut, JwtAuthenticationAttributewelche erbt IAuthenticationFilter(mehr Details zum Authentifizierungsfilter hier ).

Mit diesem Attribut können Sie jede Aktion authentifizieren: Sie müssen dieses Attribut nur für diese Aktion festlegen.

public class ValueController : ApiController
{
    [JwtAuthentication]
    public string Get()
    {
        return "value";
    }
}

Sie können auch OWIN Middleware oder DelegateHander verwenden, wenn Sie alle eingehenden Anforderungen für Ihre WebAPI überprüfen möchten (nicht spezifisch für Controller oder Aktion).

Nachfolgend finden Sie die Kernmethode des Authentifizierungsfilters:

private static bool ValidateToken(string token, out string username)
{
    username = null;

    var simplePrinciple = JwtManager.GetPrincipal(token);
    var identity = simplePrinciple.Identity as ClaimsIdentity;

    if (identity == null)
        return false;

    if (!identity.IsAuthenticated)
        return false;

    var usernameClaim = identity.FindFirst(ClaimTypes.Name);
    username = usernameClaim?.Value;

    if (string.IsNullOrEmpty(username))
       return false;

    // More validate to check whether username exists in system

    return true;
}

protected Task<IPrincipal> AuthenticateJwtToken(string token)
{
    string username;

    if (ValidateToken(token, out username))
    {
        // based on username to get more information from database 
        // in order to build local identity
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username)
            // Add more claims if needed: Roles, ...
        };

        var identity = new ClaimsIdentity(claims, "Jwt");
        IPrincipal user = new ClaimsPrincipal(identity);

        return Task.FromResult(user);
    }

    return Task.FromResult<IPrincipal>(null);
}

Der Workflow besteht darin, mithilfe der JWT-Bibliothek (NuGet-Paket oben) das JWT-Token zu validieren und dann zurückzukehren ClaimsPrincipal. Sie können weitere Überprüfungen durchführen, z. B. prüfen, ob Benutzer auf Ihrem System vorhanden sind, und bei Bedarf weitere benutzerdefinierte Überprüfungen hinzufügen. Der Code zum Validieren des JWT-Tokens und zum Zurückerhalten des Principals:

public static ClaimsPrincipal GetPrincipal(string token)
{
    try
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken;

        if (jwtToken == null)
            return null;

        var symmetricKey = Convert.FromBase64String(Secret);

        var validationParameters = new TokenValidationParameters()
        {
            RequireExpirationTime = true,
            ValidateIssuer = false,
            ValidateAudience = false,
            IssuerSigningKey = new SymmetricSecurityKey(symmetricKey)
        };

        SecurityToken securityToken;
        var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);

        return principal;
    }
    catch (Exception)
    {
        //should write log
        return null;
    }
}

Wenn das JWT-Token validiert ist und der Principal zurückgegeben wird, sollten Sie eine neue lokale Identität erstellen und weitere Informationen einfügen, um die Rollenautorisierung zu überprüfen.

Denken Sie daran, config.Filters.Add(new AuthorizeAttribute());im globalen Bereich eine Standardautorisierung hinzuzufügen , um anonyme Anforderungen an Ihre Ressourcen zu vermeiden.

Sie können Postman verwenden, um die Demo zu testen:

Token anfordern (naiv wie oben erwähnt, nur zur Demo):

GET http://localhost:{port}/api/token?username=cuong&password=1

Fügen Sie das JWT-Token für eine autorisierte Anforderung in den Header ein. Beispiel:

GET http://localhost:{port}/api/value

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImN1b25nIiwibmJmIjoxNDc3NTY1MjU4LCJleHAiOjE0Nzc1NjY0NTgsImlhdCI6MTQ3NzU2NTI1OH0.dSwwufd4-gztkLpttZsZ1255oEzpWCJkayR_4yvNL1s

Die Demo finden Sie hier: https://github.com/cuongle/WebApi.Jwt

cuongle
quelle
5
Gut erklärt von @Cuong Le, aber ich möchte noch mehr hinzufügen: Wenn Sie OWIN verwenden, überprüfen Sie die in Microsoft.Owin.Security.Jwt verfügbare UseJwtBearerAuthentication. Sie können diese eigene Middleware auf der WebAPI verwenden, um jede eingehende Anforderung automatisch zu validieren. Verwenden Sie die Owin-Startklasse, um die Middleware zu registrieren
Jek
5
@AmirPopovich Sie müssen kein Token für die Antwort festlegen. Das Token muss an einer anderen Stelle auf der Clientseite gespeichert werden. Für das Web können Sie es lokal speichern. Wenn Sie eine HTTP-Anfrage senden, setzen Sie das Token in den Header.
Cuongle
7
Wow, das ist die einfachste Erklärung, die ich seit langer Zeit gesehen habe. +100 wenn ich könnte
Gyozo Kudor
4
@ Homam: Entschuldigung für diese späte Antwort, der beste Weg zu generieren ist: varhmac = new HMACSHA256();var key = Convert.ToBase64String(hmac.Key);
cuongle
4
Jeder, der den Demo-Code aus CuongLes Repo verwendet, wird feststellen, dass es einen Fehler gibt, bei dem Anforderungen ohne Autorisierungsheader nicht behandelt werden, was bedeutet, dass jede Abfrage ohne einen solchen durchkommen kann (ein nicht so sicherer Endpunkt!). Es gibt eine Pull-Anfrage von @magicleon, um dieses Problem hier zu beheben: github.com/cuongle/WebApi.Jwt/pull/4
Chucky
11

Ich habe es mit minimalem Aufwand geschafft (genauso einfach wie mit ASP.NET Core).

Dafür benutze ich OWIN Startup.csDatei und Microsoft.Owin.Security.JwtBibliothek.

Damit die App erscheint, müssen Startup.cswir Folgendes ändern Web.config:

<configuration>
  <appSettings>
    <add key="owin:AutomaticAppStartup" value="true" />
    ...

So Startup.cssollte es aussehen:

using MyApp.Helpers;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Jwt;
using Owin;

[assembly: OwinStartup(typeof(MyApp.App_Start.Startup))]

namespace MyApp.App_Start
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseJwtBearerAuthentication(
                new JwtBearerAuthenticationOptions
                {
                    AuthenticationMode = AuthenticationMode.Active,
                    TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidAudience = ConfigHelper.GetAudience(),
                        ValidIssuer = ConfigHelper.GetIssuer(),
                        IssuerSigningKey = ConfigHelper.GetSymmetricSecurityKey(),
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true
                    }
                });
        }
    }
}

Viele von euch verwenden heutzutage ASP.NET Core. Wie Sie sehen, unterscheidet es sich nicht wesentlich von dem, was wir dort haben.

Es hat mich zuerst wirklich verwirrt, ich habe versucht, benutzerdefinierte Anbieter usw. zu implementieren. Aber ich habe nicht erwartet, dass es so einfach ist. OWINnur rockt!

Nur eine Sache zu erwähnen - nachdem ich die OWIN-Startbibliothek aktiviert habe, NSWagfunktioniert sie nicht mehr für mich (z. B. möchten einige von Ihnen möglicherweise automatisch Typoskript-HTTP-Proxys für die Angular-App generieren).

Die Lösung war auch sehr einfach - ich ersetzte NSWagdurch Swashbuckleund hatte keine weiteren Probleme.


Ok, jetzt ConfigHelperCode teilen :

public class ConfigHelper
{
    public static string GetIssuer()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["Issuer"];
        return result;
    }

    public static string GetAudience()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["Audience"];
        return result;
    }

    public static SigningCredentials GetSigningCredentials()
    {
        var result = new SigningCredentials(GetSymmetricSecurityKey(), SecurityAlgorithms.HmacSha256);
        return result;
    }

    public static string GetSecurityKey()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["SecurityKey"];
        return result;
    }

    public static byte[] GetSymmetricSecurityKeyAsBytes()
    {
        var issuerSigningKey = GetSecurityKey();
        byte[] data = Encoding.UTF8.GetBytes(issuerSigningKey);
        return data;
    }

    public static SymmetricSecurityKey GetSymmetricSecurityKey()
    {
        byte[] data = GetSymmetricSecurityKeyAsBytes();
        var result = new SymmetricSecurityKey(data);
        return result;
    }

    public static string GetCorsOrigins()
    {
        string result = System.Configuration.ConfigurationManager.AppSettings["CorsOrigins"];
        return result;
    }
}

Ein weiterer wichtiger Aspekt: ​​Ich habe JWT-Token über den Authorization- Header gesendet , sodass der Typoskript-Code für mich wie folgt aussieht:

(Der folgende Code wird von NSWag generiert. )

@Injectable()
export class TeamsServiceProxy {
    private http: HttpClient;
    private baseUrl: string;
    protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;

    constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) {
        this.http = http;
        this.baseUrl = baseUrl ? baseUrl : "https://localhost:44384";
    }

    add(input: TeamDto | null): Observable<boolean> {
        let url_ = this.baseUrl + "/api/Teams/Add";
        url_ = url_.replace(/[?&]$/, "");

        const content_ = JSON.stringify(input);

        let options_ : any = {
            body: content_,
            observe: "response",
            responseType: "blob",
            headers: new HttpHeaders({
                "Content-Type": "application/json", 
                "Accept": "application/json",
                "Authorization": "Bearer " + localStorage.getItem('token')
            })
        };

Siehe Überschriften Teil - "Authorization": "Bearer " + localStorage.getItem('token')

Alex Herman
quelle
I replaced NSWag with Swashbuckle and didn't have any further issues.Hat Swashbuckle die Fähigkeit, Typoskriptdateien zu generieren, oder haben Sie diese selbst hinzugefügt?
Crush
@crush swashbucle ist eine Backend-Bibliothek, die json bietet, wie die nuget nswag-Bibliothek nur besser. Um eine Typoskriptdatei zu erstellen, sollten Sie weiterhin das nswag-Paket von npm verwenden.
Alex Herman
Richtig, ich habe schon seit einiger Zeit Swashbuckle in meinem Projekt. Es klang, als hätten Sie vorgeschlagen, die TypeScript-Modelle anstelle von nswag zu generieren. Ich bin kein Fan von nswag ... es ist schwer. Ich habe meine eigene C # -> TypeScript-Konvertierung erstellt, die in Swashbuckle eingebunden ist. Sie generiert die Dateien als Post-Build-Prozess und veröffentlicht sie in einem npm-Feed für unsere Projekte. Ich wollte nur sicherstellen, dass ich ein Swashbuckle-Projekt nicht übersehen hatte, das bereits dasselbe tat.
Crush
7

Hier ist eine sehr minimale und sichere Implementierung einer anspruchsbasierten Authentifizierung mithilfe eines JWT-Tokens in einer ASP.NET Core-Web-API.

Zunächst müssen Sie einen Endpunkt verfügbar machen, der ein JWT-Token mit einem Benutzer zugewiesenen Ansprüchen zurückgibt:

 /// <summary>
        /// Login provides API to verify user and returns authentication token.
        /// API Path:  api/account/login
        /// </summary>
        /// <param name="paramUser">Username and Password</param>
        /// <returns>{Token: [Token] }</returns>
        [HttpPost("login")]
        [AllowAnonymous]
        public async Task<IActionResult> Login([FromBody] UserRequestVM paramUser, CancellationToken ct)
        {

            var result = await UserApplication.PasswordSignInAsync(paramUser.Email, paramUser.Password, false, lockoutOnFailure: false);

            if (result.Succeeded)
            {
                UserRequestVM request = new UserRequestVM();
                request.Email = paramUser.Email;


                ApplicationUser UserDetails = await this.GetUserByEmail(request);
                List<ApplicationClaim> UserClaims = await this.ClaimApplication.GetListByUser(UserDetails);

                var Claims = new ClaimsIdentity(new Claim[]
                                {
                                    new Claim(JwtRegisteredClaimNames.Sub, paramUser.Email.ToString()),
                                    new Claim(UserId, UserDetails.UserId.ToString())
                                });


                //Adding UserClaims to JWT claims
                foreach (var item in UserClaims)
                {
                    Claims.AddClaim(new Claim(item.ClaimCode, string.Empty));
                }

                var tokenHandler = new JwtSecurityTokenHandler();
                  // this information will be retrived from you Configuration
                //I have injected Configuration provider service into my controller
                var encryptionkey = Configuration["Jwt:Encryptionkey"];
                var key = Encoding.ASCII.GetBytes(encryptionkey);
                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Issuer = Configuration["Jwt:Issuer"],
                    Subject = Claims,

                // this information will be retrived from you Configuration
                //I have injected Configuration provider service into my controller
                    Expires = DateTime.UtcNow.AddMinutes(Convert.ToDouble(Configuration["Jwt:ExpiryTimeInMinutes"])),

                    //algorithm to sign the token
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)

                };

                var token = tokenHandler.CreateToken(tokenDescriptor);
                var tokenString = tokenHandler.WriteToken(token);

                return Ok(new
                {
                    token = tokenString
                });
            }

            return BadRequest("Wrong Username or password");
        }

jetzt müssen Sie Authentifizierung auf Ihre Dienste in Ihrer hinzufügen ConfigureServicesin Ihrem startup.cs JWT - Authentifizierung als Standard - Authentifizierungsdienst wie folgt hinzuzufügen:

services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
             .AddJwtBearer(cfg =>
             {
                 cfg.RequireHttpsMetadata = false;
                 cfg.SaveToken = true;
                 cfg.TokenValidationParameters = new TokenValidationParameters()
                 {
                     //ValidateIssuerSigningKey = true,
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Encryptionkey"])),
                     ValidateAudience = false,
                     ValidateLifetime = true,
                     ValidIssuer = configuration["Jwt:Issuer"],
                     //ValidAudience = Configuration["Jwt:Audience"],
                     //IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Key"])),
                 };
             });

Jetzt können Sie Ihren Autorisierungsdiensten folgende Richtlinien hinzufügen:

services.AddAuthorization(options =>
            {
                options.AddPolicy("YourPolicyNameHere",
                                policy => policy.RequireClaim("YourClaimNameHere"));
            });

ALTERNATIV können Sie auch (nicht erforderlich) alle Ihre Ansprüche aus Ihrer Datenbank ausfüllen , da diese beim Start Ihrer Anwendung nur einmal ausgeführt werden, und sie Richtlinien wie diesen hinzufügen:

  services.AddAuthorization(async options =>
            {
                var ClaimList = await claimApplication.GetList(applicationClaim);
                foreach (var item in ClaimList)
                {                        
                    options.AddPolicy(item.ClaimCode, policy => policy.RequireClaim(item.ClaimCode));                       
                }
            });

Jetzt können Sie den Richtlinienfilter auf eine der Methoden anwenden, für die Sie wie folgt autorisiert werden möchten:

 [HttpPost("update")]
        [Authorize(Policy = "ACC_UP")]
        public async Task<IActionResult> Update([FromBody] UserRequestVM requestVm, CancellationToken ct)
        {
//your logic goes here
}

Hoffe das hilft

Zeeshan Adil
quelle
3

Ich denke, Sie sollten einen 3D-Party-Server verwenden, um das JWT-Token zu unterstützen, und es gibt keine sofort einsatzbereite JWT-Unterstützung in WEB API 2.

Es gibt jedoch ein OWIN-Projekt zur Unterstützung eines Formats eines signierten Tokens (nicht JWT). Es funktioniert als reduziertes OAuth-Protokoll und bietet nur eine einfache Form der Authentifizierung für eine Website.

Mehr dazu können Sie zB hier lesen .

Es ist ziemlich lang, aber die meisten Teile sind Details mit Controllern und ASP.NET-Identität, die Sie möglicherweise überhaupt nicht benötigen. Am wichtigsten sind

Schritt 9: Unterstützung für die Generierung von OAuth Bearer Tokens hinzufügen

Schritt 12: Testen der Back-End-API

Dort können Sie lesen, wie Sie einen Endpunkt (z. B. "/ token") einrichten, auf den Sie vom Frontend aus zugreifen können (und Details zum Format der Anforderung).

Weitere Schritte enthalten Details zum Verbinden dieses Endpunkts mit der Datenbank usw. und Sie können die gewünschten Teile auswählen.

Ilya Chernomordik
quelle
2

In meinem Fall wird das JWT von einer separaten API erstellt, sodass ASP.NET es nur dekodieren und validieren muss. Im Gegensatz zur akzeptierten Antwort verwenden wir RSA, einen nicht symmetrischen Algorithmus, sodass die SymmetricSecurityKeyoben genannte Klasse nicht funktioniert.

Hier ist das Ergebnis.

using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Threading;
using System.Threading.Tasks;

    public static async Task<JwtSecurityToken> VerifyAndDecodeJwt(string accessToken)
    {
        try
        {
            var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"{securityApiOrigin}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
            var openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);
            var validationParameters = new TokenValidationParameters()
            {
                ValidateLifetime = true,
                ValidateAudience = false,
                ValidateIssuer = false,
                RequireSignedTokens = true,
                IssuerSigningKeys = openIdConfig.SigningKeys,
            };
            new JwtSecurityTokenHandler().ValidateToken(accessToken, validationParameters, out var validToken);
            // threw on invalid, so...
            return validToken as JwtSecurityToken;
        }
        catch (Exception ex)
        {
            logger.Info(ex.Message);
            return null;
        }
    }
Ron Newcomb
quelle