2015-06-18 23 views
10

Ciao così ho cercato di raggiungere SSO WS-Fed sulla mia applicazione web MVC6, ho letto un po 'sull'autenticazione e tutti per identificare il mio requisiti. Devo usare WsFederationAuth in modo che nessun protocollo oauth e saml possa funzionare per me.Accesso WS-Federation Asp.NET 5 MVC 6 ADFS

Edit: Dopo @Pinpoint suggerimento ho cercato di usare Owin middleware per realizzare la connessione, ma userò il DNX451 quadro completo piuttosto che DNXCore ma è qualcosa durante l'attesa per WS-Fed di essere supportati da vNext.

Pinpointadapter extension:

public static class AppBuilderExtensions 
    { 
#if !DNXCORE50 
     public static IApplicationBuilder UseOwinAppBuilder(this IApplicationBuilder app, 
      Action<IAppBuilder> configuration) 
     { 
      if (app == null) 
      { 
       throw new ArgumentNullException(nameof(app)); 
      } 

      if (configuration == null) 
      { 
       throw new ArgumentNullException(nameof(configuration)); 
      } 


      return app.UseOwin(setup => setup(next => 
      { 
       var builder = new AppBuilder(); 
       var lifetime = (IApplicationLifetime) app.ApplicationServices.GetService(typeof (IApplicationLifetime)); 

       var properties = new AppProperties(builder.Properties); 
       properties.AppName = app.ApplicationServices.GetApplicationUniqueIdentifier(); 
       properties.OnAppDisposing = lifetime.ApplicationStopping; 
       properties.DefaultApp = next; 

       configuration(builder); 

       return builder.Build<Func<IDictionary<string, object>, Task>>(); 
      })); 
     } 
#endif 
    } 

E in startup.cs:

#if !DNXCORE50 
      app.UseOwinAppBuilder(owin => 
      { 
       owin.UseWsFederationAuthentication(new WsFederationAuthenticationOptions 
       { 
        MetadataAddress = 
         "https://mysite.accesscontrol.windows.net/FederationMetadata/2007-06/FederationMetadata.xml", 
        Wtrealm = "http://localhost:62569/", 
        SignInAsAuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType, 
        AuthenticationType = "adfs", 
        SecurityTokenHandlers = new SecurityTokenHandlerCollection 
        { 
         new EncryptedSecurityTokenHandler 
         { 
          Configuration = new SecurityTokenHandlerConfiguration 
          { 
           IssuerTokenResolver = new X509CertificateStoreTokenResolver(StoreName.My, 
            StoreLocation.LocalMachine) 
          } 
         }, 
         new Saml2SecurityTokenHandler 
         { 
          CertificateValidator = X509CertificateValidator.None, 

         } 
        } 
       }); 
      }); 
#endif 

Sento Mi sto avvicinando a una soluzione, ma non è ancora finita. Ho difficoltà nel gestire il token (dopo l'autenticazione contro l'adfs)

ottengo questo errore con afaiu il token:

SecurityTokenValidationException: IDX10201: Nessuno dei i SecurityTokenHandlers in grado di leggere il 'SecurityToken':

<Assertion ID="_851fc402-2e9c-4ff8-a743-7d65612255b9" IssueInstant="2015-06-22T16:16:03.852Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> 
    <Issuer>https://mysite.accesscontrol.windows.net/</Issuer> 
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
     <ds:SignedInfo> 
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> 
      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> 
      <ds:Reference URI="#_851fc402-2e9c-4ff8-a743-7d65612255b9"> 
       <ds:Transforms> 
        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> 
        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> 
       </ds:Transforms> 
       <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> 
       <ds:DigestValue>xZdzOnNIG5Ia***********t0feMWIZMLnY=</ds:DigestValue> 
      </ds:Reference> 
     </ds:SignedInfo> 
     <ds:SignatureValue>KmuScnZBdxyaAJrfLgB9AYheUdR*****************************Xs4o8R+eMCPdWNsDjhLu500UlCgitYerjpLTTyRRdwvFo8T7LlsXO2yjv3dx83Yn+GthE+FswNRH07yIHF5wo5+/TAwiVzg+9SDbK+Nj84PdLMxwIfALAebf4/ECdpqkWvt2ligzFoQckEgZMRepOcAVfBxfELyJSUDAjnpfJCrlCQip0nykC+5R37X00flIlB563p48veeLIt0JaUdG4bwtQ8OCMg1KeD5gYix9p4E3TQ7QovN0HDoWTurLK/0H01IS73fIe6/k6DBA==</ds:SignatureValue> 
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 
      <X509Data> 
       <X509Certificate>MIIDSjCCAjagAwIBAgIQrcBhMtovuJ**********************MDExLzAtBgNVBAMTJm1hcmdvY29uc2VpbC5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE1MDYxNjA4MTYzOFoXDTIwMDUzMTIyMDAwMFowMTEvMC0GA1UEAxMmbWFyZ29jb25zZWlsLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpeZseXX1IYTABUOPr7nfIAXc7cXAI0k+vR3qEbvy0UxEhYAkAocQR2qUTPQ8D1v4lPp59tnHKBGJ0eHt9DYm/SyKkfHsWfqsysZx5NHXSJIhy/SgHwpd8b2q1NKxqBRLrdJKyAua+WWza4p/HMFjEVoN/upZtngSqxUKO/oYqy6m7smkz8vwjzpJR8tyqN881XBQzvryiF/i3ZPFQqlCT9263TMcAGPpym9uvxHzFPPx3u8IDz3AQydyHeViaJhiXGic0VEcm6LMn3JLOYqAzJnv8z89NdpsL4ynv1ekytt/8yyza3CnsU1E4tFDj1HU3785aFZ1xm6wr1MUK9VOTAgMBAAGjZjBkMGIGA1UdAQRbMFmAEN1alzwM3lJSHdh4LFl7uxmhMzAxMS8wLQYDVQQDEyZtYXJnb2NvbnNlaWwuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQrcBhMtovuJ9MilbEjMjS7TAJBgUrDgMCHQUAA4IBAQAsQ5jNKvS2fLtqs9oB6DGTXdI5nAli5UyvZUQlnfnMvgYjJKrZu79iMe9iu88cmtwZVifG14SRbVdTjUOzngIWAJ5KAQk5t//wSkwgAS+U6AFYI/mee9NLEvOEhrRbpGUP0oL504OZ9zTDeXmGu2FybRB2TvdTKLaeVsBvwqgP33QFkcuPK50fCGC1l3SecIeyWL5fsiw/2+GuTKHjCaeRqnYBgDTINptc9PGayLPBTjs4UPzbccmaYyuanmTAMZGU0iRoGJYet2uAasT52QvWZqD0NUZbWyR1N8CBf5EIW2S/TrpoOBYNgZQU5n9PRJjTBhESHXjfa8RipC8RXU9o</X509Certificate> 
      </X509Data> 
     </KeyInfo> 
    </ds:Signature> 
    <Subject> 
     <NameID>***********</NameID> 
     <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" /> 
    </Subject> 
    <Conditions NotBefore="2015-06-22T16:16:03.836Z" NotOnOrAfter="2015-06-22T17:16:03.836Z"> 
     <AudienceRestriction> 
      <Audience>http://localhost:62569/</Audience> 
     </AudienceRestriction> 
    </Conditions> 
    <AttributeStatement> 
     <Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid"> 
      <AttributeValue>********************</AttributeValue> 
     </Attribute> 
     <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"> 
      <AttributeValue>************</AttributeValue> 
     </Attribute> 
     <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"> 
      <AttributeValue>G****l</AttributeValue> 
     </Attribute> 
     <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"> 
      <AttributeValue>L****s</AttributeValue> 
     </Attribute> 
     <Attribute Name="http://schemas.microsoft.com/identity/claims/identityprovider"> 
      <AttributeValue>https://sts.windows.net/7102feaa-34af-4756-85ce-b0f69766d78d/</AttributeValue> 
     </Attribute> 
     <Attribute Name="http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"> 
      <AttributeValue>https://sts.windows.net/7102feaa-34af-4756-85ce-b0f69766d78d/</AttributeValue> 
     </Attribute> 
    </AttributeStatement> 
    <AuthnStatement AuthnInstant="2015-06-22T14:26:14.020Z"> 
     <AuthnContext> 
      <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef> 
     </AuthnContext> 
    </AuthnStatement> 
</Assertion> 

risposta

3

Come già capito, il middleware WS-Federation non è stato portato su ASP.NET 5 ancora, ma niente panico, sarà sicuramente: https://twitter.com/blowdart/status/610526268908535808

Nel frattempo, è possibile utilizzare il/Katana 3 WS-Federation middleware OWIN in un'applicazione ASP.NET 5 con un piccolo IAppBuilder/IApplicationBuilder adattatore (come questo: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/vNext/samples/Mvc/Mvc.Server/Extensions/AppBuilderExtensions.cs#L50), ma ovviamente, non sarà essere compatibile con dnxcore50.

Se si dispone di una versione ADFS recente, è anche possibile prendere in considerazione il passaggio a OAuth2.

+1

In questo caso, sarebbe ADFS essere il provider di identità? –

+0

Sì, anche se "provider di identità" è piuttosto un termine OpenID Connect, che non è supportato da ADFS (a differenza della sua controparte cloud: AAD). "server di autorizzazione" sarebbe il nome esatto in questo caso. – Pinpoint

+0

Grazie a LOT per questo @Pinpoint, guarderò in quel lunedì (sono uno stagista molto motivato ma ci sono dei limiti alla mia motivazione: D). Mi piacerebbe sicuramente usare OAuth2, ma il mio capo non vuole fare nessuna modifica sulla parte ADFS, devo adattare tutto alla parte esistente, quindi usare ws-federation. Ho provato a dirgli che IMO era nutrito con tecnologia vecchia e come lui insisteva nell'usare .NET5 e tutte le nuove cose, quindi non era logico attenersi a una vecchia tecnologia per un solo aspetto del progetto. Ma mi ha appena detto che ero pigro e volevo solo fare una soluzione ... – Lomithrani

1

Ho scoperto come ottenere le attestazioni dalla richiesta http proveniente da ADFS utilizzando le classi ASP.NET precedenti in un modo che non tocchi web.config.

Speriamo che questo codice è utile a qualcuno:

using Microsoft.AspNet.Http; 
using Microsoft.Extensions.Configuration; 
using System; 
using System.Collections.Specialized; 
using System.IdentityModel.Configuration; 
using System.IdentityModel.Protocols.WSTrust; 
using System.IdentityModel.Selectors; 
using System.IdentityModel.Services; 
using System.IdentityModel.Tokens; 
using System.IO; 
using System.Security.Claims; 
using System.Security.Cryptography.X509Certificates; 
using System.ServiceModel.Security; 
using System.Text; 
using System.Xml; 

public class FederationHelper 
{ 
    public ClaimsIdentity GetClaimsIdentityFromResponse(IConfigurationRoot configurationRoot, HttpContext context) 
    { 
     var absoluteUri = string.Concat(
        context.Request.Scheme, 
        "://", 
        context.Request.Host.ToUriComponent(), 
        context.Request.PathBase.ToUriComponent(), 
        context.Request.Path.ToUriComponent(), 
        context.Request.QueryString.ToUriComponent()); 

     var values = new NameValueCollection(); 

     foreach (var item in context.Request.Query) 
     { 
      values.Add(item.Key, item.Value); 
     } 

     foreach (var item in context.Request.Form) 
     { 
      values.Add(item.Key, item.Value); 
     } 

     var federation = new FederationSettings 
     { 
      AudienceUri = "http://contoso", 
      Endpoint = "http://sts/ls", 
      IssuerName = "http://sts/trust", 
      IssuerThumbprint = "[thumbprint]", 
      Realm = "https://myapp" 
     }; 

     var identityConfiguration = new IdentityConfiguration(false); 
     identityConfiguration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(federation.AudienceUri)); 

     var issuers = new ConfigurationBasedIssuerNameRegistry(); 
     issuers.ConfiguredTrustedIssuers.Add(federation.IssuerThumbprint, federation.IssuerName); 
     identityConfiguration.IssuerNameRegistry = issuers; 

     var tokenHandler = new SamlSecurityTokenHandler(); 

     tokenHandler.Configuration = new SecurityTokenHandlerConfiguration(); 
     tokenHandler.Configuration.AudienceRestriction.AudienceMode = AudienceUriMode.Always; 
     tokenHandler.Configuration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(federation.AudienceUri)); 
     tokenHandler.Configuration.IssuerNameRegistry = identityConfiguration.IssuerNameRegistry; 
     tokenHandler.Configuration.CertificateValidationMode = X509CertificateValidationMode.None; 
     tokenHandler.Configuration.RevocationMode = X509RevocationMode.NoCheck; 
     tokenHandler.Configuration.CertificateValidator = X509CertificateValidator.None; 

     var message = (SignInResponseMessage)WSFederationMessage.CreateFromNameValueCollection(new Uri(absoluteUri), values); 
     var token = CreateSecurityToken(tokenHandler, identityConfiguration, message); 
     var claims = tokenHandler.ValidateToken(token); 

     return claims[0]; 
    } 

    public SecurityToken CreateSecurityToken(SamlSecurityTokenHandler handler, IdentityConfiguration configuration, SignInResponseMessage message) 
    { 
     var quotas = new XmlDictionaryReaderQuotas(); 

     using (var reader = XmlDictionaryReader.CreateTextReader(Encoding.UTF8.GetBytes(message.Result), quotas)) 
     { 
      var serializer = new WSFederationSerializer(reader); 
      var context = new WSTrustSerializationContext(configuration.SecurityTokenHandlerCollectionManager); 

      var xml = serializer.CreateResponse(message, context).RequestedSecurityToken.SecurityTokenXml.OuterXml; 

      return ReadToken(handler, xml, quotas); 
     } 
    } 

    SecurityToken ReadToken(SamlSecurityTokenHandler handler, string xml, XmlDictionaryReaderQuotas quotas) 
    { 
     using (var reader = new StringReader(xml)) 
     { 
      using (var xmlReader = XmlReader.Create(reader)) 
      { 
       xmlReader.MoveToContent(); 

       return handler.ReadToken(xmlReader); 
      } 
     } 
    } 
} 
+0

Sembra molto simile a quello che avevo fatto alla fine da quello che ricordo @fiat dovresti controllare che – Lomithrani

Problemi correlati