2017-09-19 69 views
5

Mam aplikację .Net Core 2.0, która używa tokenów JWT do autoryzacji użytkownika. To wszystko działa dobrze, ale chcę mieć jakiś mechanizm klucza API, aby umożliwić innym aplikacjom integrację, ale nie wydaje mi się, żeby działało to z bieżącym uwierzytelnieniem..Net Core JWT Uwierzytelnianie za pomocą niestandardowego klucza API Middleware

Kod:

Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, 
      IMemoryCache cache, IServiceProvider serviceProvider) 
{ 
    app.UseAuthentication(); 

    ApiKeyMiddlewear(app, serviceProvider); 

    app.UseMvc(routes => 
    { 
     routes.MapRoute(
       name: "default", 
       template: "{controller=Home}/{action=Index}/{id?}"); 

      routes.MapSpaFallbackRoute(
       name: "spa-fallback", 
       defaults: new { controller = "Home", action = "Index" }); 
     }); 
    } 
} 


    private static void ApiKeyMiddlewear(IApplicationBuilder app, IServiceProvider serviceProvider) 
    { 
     app.Use(async (context, next) => 
     { 
      if (context.Request.Path.StartsWithSegments(new PathString("/api"))) 
      { 
       // Let's check if this is an API Call 
       if (context.Request.Headers["ApiKey"].Any()) 
       { 
        // validate the supplied API key 
        // Validate it 
        var headerKey = context.Request.Headers["ApiKey"].FirstOrDefault(); 
        var settingsProvider = serviceProvider.GetService<ISettingsService<OmbiSettings>>(); 
        var ombiSettings = settingsProvider.GetSettings(); 
        var valid = ombiSettings.ApiKey.Equals(headerKey, StringComparison.CurrentCultureIgnoreCase); 
        if (!valid) 
        { 
         context.Response.StatusCode = (int) HttpStatusCode.Unauthorized; 
         await context.Response.WriteAsync("Invalid API Key"); 
        } 
        else 
        { 
         var identity = new GenericIdentity("API"); 
         identity.AddClaim(new System.Security.Claims.Claim("Origin", "Api")); 
         identity.AddClaim(new System.Security.Claims.Claim("role", "Admin")); 

         var principal = new GenericPrincipal(identity, new[] {"ApiUser"}); 
         context.User = principal; 
         await next(); 
        } 
       } 
       else 
       { 
        await next(); 
       } 
      } 
      else 
      { 
       await next(); 
      } 
     }); 
    } 
} 

Więc w kodzie powyżej widać, że jestem przechwytywanie żądań HTTP, które zapewniają nagłówka nazywa ApiKey a następnie zatwierdź ją, co mam mam zapisane. Ta część wszystko działa, ale podczas wywoływania metody API z Authorize przypisują to nie działa i mam następujące dzienniki błędach:

2017-09-19 08:15:17.280 +01:00 [Information] Request starting HTTP/1.1 POST http://localhost:52038/api/v1/Identity/ application/json 372 
2017-09-19 08:15:21.967 +01:00 [Information] Authorization failed for user: "API". 
2017-09-19 08:15:21.976 +01:00 [Information] Authorization failed for the request at filter '"Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter"'. 
2017-09-19 08:15:21.981 +01:00 [Information] Executing ForbidResult with authentication schemes ([]). 
2017-09-19 08:15:21.991 +01:00 [Information] AuthenticationScheme: "Bearer" was forbidden. 
2017-09-19 08:15:21.996 +01:00 [Information] Executed action "Ombi.Controllers.IdentityController.CreateUser (Ombi)" in 38.8268ms 
2017-09-19 08:15:22.004 +01:00 [Information] Request finished in 4723.032ms 403 

Teraz zgaduję to zrobić z prośba tylko dostarczanie ApiKey nagłówek a nie nagłówek Authorization z poprawnym tokenem JWT.

W jaki sposób mogę dostarczyć nagłówek ApiKey i gdy nie ma nagłówka ApiKey, a następnie powrócić do żądania tokenu JWT?

+0

Czy używasz Asp.net Identity? –

+0

@AramKocharyan Tak –

+0

Czy używasz atrybutu "Authorize" z właściwością 'Roles'? Jak '[Authorize (Roles =" foo ")]' –

Odpowiedz

3

Zastosowanie Claim("role", "Admin") do GenericPrincipal nic nie zmieni, ponieważ GenericPrincipal nie mają nic wspólnego z roszczeniami ról. Jeśli więc chcesz zastosować rolę administratora do GenericPrincipal, musisz dodać ją do parametru konstruktora:

var principal = new GenericPrincipal(identity, new[] {"Admin","ApiUser"}); 
context.User = principal;