2014-05-21 6 views
12

Sto cercando di implementare la reimpostazione della password su un sito Web ASP.NET MVC basato su OWIN/Katana in esecuzione in Azure.L'operazione di protezione dati non è andata a buon fine in Azure utilizzando OWIN/Katana

Funziona correttamente quando viene eseguito localmente ma non riesce nella produzione.

ho creare un provider UserToken

userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("PasswordReset")) 

Ma quando tento di generare il token come segue ottengo uno spettacolo un'eccezione alla fine.

var resetToken = await UserManager.GeneratePasswordResetTokenAsync(user.Id); 

System.Security.Cryptography.CryptographicException: The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating. 
    at System.Security.Cryptography.ProtectedData.Protect(Byte[] userData, Byte[] optionalEntropy, DataProtectionScope scope) 
    at System.Security.Cryptography.DpapiDataProtector.ProviderProtect(Byte[] userData) 
    at System.Security.Cryptography.DataProtector.Protect(Byte[] userData) 
    at Microsoft.Owin.Security.DataProtection.DpapiDataProtector.Protect(Byte[] userData) 
    at Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider`2.<GenerateAsync>d__0.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at Microsoft.AspNet.Identity.UserManager`2.<GenerateUserTokenAsync>d__e9.MoveNext() 
+0

hai trovato la soluzione? – Dragouf

+0

Nota ancora. Qualche idea? –

+0

sì, ho trovato una soluzione, ma non sono totalmente soddisfatto. Sembra che sia dovuto al parametro AppName che non è lo stesso ovunque nell'applicazione. Quindi ho usato i parametri dell'app della chiamata di configurazione (app IAppBuilder) da OwinStartupAttribute per installare l'IDataPRovider e sembra funzionare. Per ottenere l'oggetto dataprovider puoi farlo in questo modo: app.GetDataProtectionProvider(). Dimmi se funziona – Dragouf

risposta

3

Ho trovato una soluzione. Io non sono esattamente sicuro se tutti i passi sono necessari per farlo funzionare, ma ora la mia app funziona perfettamente:

1.- Aggiorna il tuo web.config per supportare securityTokenHandlers

<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> 
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> 

nel nodo configSections. E

<securityTokenHandlers> 
    <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, 
       System.IdentityModel, Version=4.0.0.0, Culture=neutral, 
       PublicKeyToken=B77A5C561934E089" /> 

    <add 
     type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, 
      System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, 
      PublicKeyToken=B77A5C561934E089"> 
     <sessionTokenRequirement lifetime="00:30:00"></sessionTokenRequirement> 
    </add> 
    </securityTokenHandlers> 

</identityConfiguration> 

come nodo normale. 2.- Nei tuoi Startup.Auth.cs di file, aggiornare il ConfigureAuth (IAppBuilder app) in questo modo:

public void ConfigureAuth(IAppBuilder app) 
     { 

      UserManagerFactory =() => 
      { 
       var userManager = new UserManager<SIAgroUser>(new UserStore<UserType>(new SIAgroUserDbContext())); 

       IDataProtectionProvider provider = app.GetDataProtectionProvider(); 

       //userManager.UserTokenProvider = new Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider<UserType>(provider.Create("PasswordReset")); 
       if (provider != null) 
       { 
        userManager.UserTokenProvider = new DataProtectorTokenProvider<UsertType, string>(provider.Create("PasswordReset")); 
       } 

       return userManager; 
      }; 

      OAuthOptions = new OAuthAuthorizationServerOptions 
      { 
       TokenEndpointPath = new PathString("/Token"), 
       Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory), 
       AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), 
       AllowInsecureHttp = true 
      }; 
      // Enable the application to use a cookie to store information for the signed in user 
      // and to use a cookie to temporarily store information about a user logging in with a third party login provider 
      app.UseCookieAuthentication(new CookieAuthenticationOptions()); 
      app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); 

      // Enable the application to use bearer tokens to authenticate users 
      app.UseOAuthBearerTokens(OAuthOptions); 

      // Uncomment the following lines to enable logging in with third party login providers 
      //app.UseMicrosoftAccountAuthentication(
      // clientId: "", 
      // clientSecret: ""); 

      //app.UseTwitterAuthentication(
      // consumerKey: "", 
      // consumerSecret: ""); 

      //app.UseFacebookAuthentication(
      // appId: "", 
      // appSecret: ""); 

      //app.UseGoogleAuthentication(); 



     } 

3.- ripulire la costruzione della classe di avvio in questo modo:

static Startup() 
{ 
    PublicClientId = "self"; 
} 

Che ha funzionato per me :) Spero che funzioni anche per te

+0

Penso che questa parte sia importante: IDataProtectionProvider provider = app.GetDataProtectionProvider(); Come ho detto nel mio precedente commento, penso che sia un problema con l'AppName. Se installi tu stesso il provider di dataprotection, imposterai un nome diverso dal nome dell'applicazione che usa ... – Dragouf

+0

E penso che utilizzare il contesto di Owin per istanziare il gestore degli utenti sia meglio se non usi alcuna IOS: app. CreatePerOwinContext (ExtranetDbContext.Create); app.CreatePerOwinContext (ApplicationUserManager.Create); – Dragouf

0

Ottenere l'UserManager da Owin Pipeline, come impostato in App_Start/Startup.Auth.cs, funziona su Azure. Non sono sicuro di come funzioni in modo specifico. DpApi dovrebbe funzionare in Azure con la soluzione descritta nel primo collegamento.

Se la DpApi ha una chiave di macchina statica impostata in Web.config, tutte le macchine server saranno in grado di decrittografare i dati crittografati creati da un'altra macchina nella webfarm.

(codice come indicato nel modello di serie - da AccountController.cs)

private UserManager userManager; 
    public UserManager UserManager 
    { 
     get { return userManager ?? HttpContext.GetOwinContext().GetUserManager<UserManager>(); } 
     private set { userManager = value; } 
    } 
2

, vedere il mio my answer a questa domanda. Una soluzione molto più semplice può essere raggiunto utilizzando IAppBuilder.GetDataProtectionProvider()

1

Questo errore si verifica per me su un provider di hosting condiviso, alla linea:

var provider = new DpapiDataProtectionProvider("SITENAME"); 

La soluzione era abbastanza semplice.In primo luogo cambiare la linea di cui sopra a questo:

var provider = new MachineKeyProtectionProvider(); 

quindi creare un nuovo file, che ho nel mio spazio dei nomi di utilità, in questo modo:

using Microsoft.Owin.Security.DataProtection; 
using System.Web.Security; 

namespace <yournamespace>.Utilities 
{ 
    public class MachineKeyProtectionProvider : IDataProtectionProvider 
    { 
     public IDataProtector Create(params string[] purposes) 
     { 
      return new MachineKeyDataProtector(purposes); 
     } 
    } 

    public class MachineKeyDataProtector : IDataProtector 
    { 
     private readonly string[] _purposes; 

     public MachineKeyDataProtector(string[] purposes) 
     { 
      _purposes = purposes; 
     } 

     public byte[] Protect(byte[] userData) 
     { 
      return MachineKey.Protect(userData, _purposes); 
     } 

     public byte[] Unprotect(byte[] protectedData) 
     { 
      return MachineKey.Unprotect(protectedData, _purposes); 
     } 
    } 
} 

Et voilà! Problema risolto. Ricorda, nel tuo metodo di reimpostazione della password, dovrai anche utilizzare questo provider, altrimenti riceverai un errore Invalid Token.

4

Ho lo stesso problema quando provo a generare token con identità ASP .Net e funzione di login personalizzata in Web API.

"The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating." 

Quello che ho fatto è semplicemente creare un impostazioni delle applicazioni chiamato WEBSITE_LOAD_USER_PROFILE in Microsoft Azure e impostarlo a 1. Tale soluzione è funziona per me.

È possibile vedere il dettaglio here

+0

la soluzione più semplice qui, e proprio come dice il link, avevo bisogno di evitare i piani BASIC e SHARED per applicare queste impostazioni. – ericosg

Problemi correlati