6

Ist es mit einer Owin Middleware-Implementierung möglich, Ansprüche vor der Ausführung eines Web-API-Controllers hinzuzufügen?Hinzufügen von Ansprüchen mit Owin Middleware

eine OwinMiddleware Implementierung und fügte hinzu, eine Identität Erstellt:

var id = new ClaimsIdentity(); 
id.AddClaim(new Claim("Whatever", "is possible")); 
context.Authentication.User.AddIdentity(id); 

await Next.Invoke(context); 

Aber auch diese Invoke Methode aufrufen, die Identitäten nicht aktualisiert werden (nur die internen Ansprüche Array). Und der Controller bekommt natürlich bei seiner Ausführung nie den neuen Dummy-Anspruch.

Ideen?

+1

Nach einem Gespräch mit @Pinpoint auf der Owin Lobby in JabbR scheint es, dass der einzige Weg in die Authentifizierungs-Linie durch die UseOAuthBearerAuthentication des IAppBuilder ist durch einen speziellen Provider angeben. Ansprüche können dann dem Identitätskontext hinzugefügt werden (context.Ticket.Identity.AddClaim (...)). Dies geschieht auf Anfrage. –

Antwort

1

können Sie nützlich finden von Authorizate Attribut vererben und sich Ihren Anforderungen gerecht zu werden:

public class DemoAuthorizeAttribute : AuthorizeAttribute 
    {  

     public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext){ 
      if (Authorize(actionContext)){ 
       return; 
      } 
      HandleUnauthorizedRequest(actionContext); 
     } 

     protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext){ 
      var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized; 

//Adding your code here 
var id = new ClaimsIdentity(); 
id.AddClaim(new Claim("Whatever", "is possible")); 
context.Authentication.User.AddIdentity(id); 

      challengeMessage.Headers.Add("WWW-Authenticate", "Basic"); 
      throw new HttpResponseException(challengeMessage); 
     } 

     private bool Authorize(System.Web.Http.Controllers.HttpActionContext actionContext){ 
      try{ 
       var someCode = (from h in actionContext.Request.Headers where h.Key == "demo" select h.Value.First()).FirstOrDefault(); 

       // or check for the claims identity property. 
       return someCode == "myCode"; 
      } 
      catch (Exception){ 
       return false; 
      } 
     } 
    } 

Und in Ihrem Controller:

[DemoAuthorize] 
public class ValuesController : ApiController{ 

Hier ist ein Link auf andere benutzerdefinierte Implemenation für WebAPI Berechtigungen :

http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/

+0

Das einzige Problem, das ich gefunden habe, ist, wenn Sie mehrere Autorisierungsmethoden unterstützen, z. OAuth und HMAC müssen Sie die Claims Enrichment an mehreren Stellen implementieren, daher meine Antwort unten. –

0

Es gibt bereits eine Klasse, die Ansprüche Anreicherung ClaimsAuthenticationManager zur Verfügung stellen kann, was Sie es Ihre domänenspezifische Ansprüche erweitern können so behandelt, zum Beispiel ...

public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager 
{ 
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) 
    { 
     if (!incomingPrincipal.Identity.IsAuthenticated) 
     { 
      return base.Authenticate(resourceName, incomingPrincipal); 
     } 

     return AddApplicationClaims(incomingPrincipal); 
    } 

    private ClaimsPrincipal AddApplicationClaims(ClaimsPrincipal principal) 
    { 
     // TODO: Add custom claims here based on current principal. 

     return principal; 
    } 
} 

nächste Aufgabe ist es angemessen Middleware zu schaffen, diese aufzurufen. Für meine Projekte habe ich die folgenden Klassen geschrieben ...

/// <summary> 
/// Middleware component to apply claims transformation to current context 
/// </summary> 
public class ClaimsTransformationMiddleware 
{ 
    private readonly Func<IDictionary<string, object>, Task> next; 
    private readonly IServiceProvider serviceProvider; 

    public ClaimsTransformationMiddleware(Func<IDictionary<string, object>, Task> next, IServiceProvider serviceProvider) 
    { 
     this.next = next; 
     this.serviceProvider = serviceProvider; 
    } 

    public async Task Invoke(IDictionary<string, object> env) 
    { 
     // Use Katana's OWIN abstractions 
     var context = new OwinContext(env); 

     if (context.Authentication != null && context.Authentication.User != null) 
     { 
      var manager = serviceProvider.GetService<ClaimsAuthenticationManager>(); 
      context.Authentication.User = manager.Authenticate(context.Request.Uri.AbsoluteUri, context.Authentication.User); 
     } 

     await next(env); 
    } 
} 

Und dann eine Beschaltungsleitung ...

public static class AppBuilderExtensions 
{ 
    /// <summary> 
    /// Add claims transformation using <see cref="ClaimsTransformationMiddleware" /> any depdendency resolution is done via IoC 
    /// </summary> 
    /// <param name="app"></param> 
    /// <param name="serviceProvider"></param> 
    /// <returns></returns> 
    public static IAppBuilder UseClaimsTransformation(this IAppBuilder app, IServiceProvider serviceProvider) 
    { 
     app.Use<ClaimsTransformationMiddleware>(serviceProvider); 

     return app; 
    } 
} 

Ich weiß, dass dieser Service Locator anti-Muster ist aber IServiceProvider ist mit Container neutral und scheint der akzeptierte Weg zu sein, Abhängigkeiten in Owin Middleware zu setzen.

Lesen Sie diese nach oben in Ihrem Startup verdrahten müssen, folgendes Beispiel setzt voraus, Unity und Registrierung/Aussetzen eine IServiceLocator Eigenschaft ...

// Owin config 
app.UseClaimsTransformation(UnityConfig.ServiceLocator); 
0

Dies ist, wie ich das Hinzufügen einen neuen Anspruchs in owin Middleware endete, basierend auf dem OP-Kommentar zum Einhängen in UseOAuthBearerAuthentication. Es verwendet IdentityServer3.AccessTokenValidation, das UseOAuthBearerAuthentication intern aufruft und den OAuthBearerAuthenticationProvider an es übergibt.

using System.Security.Claims; 
using System.Threading.Tasks; 
using IdentityServer3.AccessTokenValidation; 
using Owin; 
using Microsoft.Owin.Security.OAuth; 

//... 

public void Configuration(IAppBuilder app) 
{ 
    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions 
    { 
     Authority = "http://127.0.0.1/identityserver", 
     TokenProvider = new OAuthBearerAuthenticationProvider 
     { 
      OnValidateIdentity = AddClaim 
     } 
    }); 
} 

private Task AddClaim(OAuthValidateIdentityContext context) 
{ 
    context.Ticket.Identity.AddClaim(new Claim("test", "123")); 
    return Task.CompletedTask; 
}