J'essaie d'implémenter la réinitialisation du mot de passe sur un site Web ASP.NET MVC basé sur OWIN/Katana qui s'exécute dans Azure.
Il fonctionne bien lorsqu'il est exécuté localement mais échoue en production.
Je crée un fournisseur UserToken
userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(provider.Create("PasswordReset"))
Mais quand j'essaie de générer le jeton comme suit
var resetToken = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
Je reçois l'exception suivante.
System.Security.Cryptography.CryptographicException: Les données l'opération de protection a échoué. Cela peut avoir été causé par ne pas avoir le profil d'utilisateur chargé pour l'utilisateur du thread actuel contexte, ce qui peut être le cas lorsque le thread emprunte l'identité de . sur System.Security.Cryptography.ProtectedData.Protect (Byte [] userData, Byte [] optionalEntropy, portée de DataProtectionScope) sur System.Security.Cryptography.DpapiDataProtector.ProviderProtect (Byte [] userData) sur System.Security.Cryptography.DataProtector.Protect (Byte [] userData) sur Microsoft.Owin.Security.DataProtection.DpapiDataProtector.Protect (Byte [] userData) sur Microsoft.AspNet.Identity.Owin.DataProtectorTokenProvider 2.d__0.MoveNext () --- Trace de fin de pile depuis l'emplacement précédent où une exception a été levée --- sur System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (tâche tâche) à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (Task tâche). chez Microsoft.AspNet.Identity.UserManager`2.d__e9.MoveNext ()
J'ai le même problème lorsque j'essaie de générer un jeton avec ASP. Identité Net et fonction de connexion personnalisée dans l'API Web.
"L'opération de protection des données a échoué. Cela peut avoir été provoqué par le fait que le profil utilisateur n'a pas été chargé pour le contexte utilisateur Du thread actuel, ce qui peut être le cas lorsque le thread se fait passer pour une identité."
Ce que j'ai fait est simplement de créer un paramètre d'application appelé WEBSITE_LOAD_USER_PROFILE
dans Microsoft Azure et de le définir sur 1. Cette solution fonctionne pour moi.
Vous pouvez voir le détail ici
S'il vous plaît voir mon ma réponse à cette question. Une solution beaucoup plus simple peut être obtenue en utilisant IAppBuilder.GetDataProtectionProvider()
J'ai trouvé une solution. Je ne sais pas exactement si toutes les étapes sont nécessaires pour que cela fonctionne, mais maintenant, mon application fonctionne parfaitement:
1.- Mettez à jour votre web.config pour prendre en charge 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"/>
dans le noeud configSections. Et
<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>
en tant que noeud normal . 2.- Dans votre fichier Startup.Auth.cs, mettez à jour votre ConfigureAuth (application IAppBuilder) comme suit:
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.- Nettoyez le constructeur de votre classe de démarrage comme ceci:
static Startup()
{
PublicClientId = "self";
}
Cela a fonctionné pour moi :) J'espère que cela fonctionne pour vous aussi
J'ai mis celui-ci sur la glace pendant un moment, mais j'ai été obligé d'y revenir. J'ai trouvé la solution ici: La génération d'un jeton de réinitialisation du mot de passe ne fonctionne pas dans le site Web Azure
Cette erreur se produit pour moi sur un fournisseur d'hébergement partagé, à la ligne:
var provider = new DpapiDataProtectionProvider("SITENAME");
La solution était assez simple. Commencez par changer la ligne ci-dessus en ceci:
var provider = new MachineKeyProtectionProvider();
Ensuite, créez un nouveau fichier, que j'ai dans mon espace de noms Utilities, comme suit:
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à! Problème résolu. N'oubliez pas que dans votre méthode de contrôleur de réinitialisation de mot de passe, vous devrez également utiliser ce fournisseur, sinon vous obtiendrez une erreur Invalid Token
.
L'obtention de UserManager à partir du pipeline Owin, telle qu'elle est définie dans App_Start/Startup.Auth.cs, fonctionne sur Azure. Je ne sais pas comment cela fonctionne spécifiquement. DpApi doit fonctionner dans Azure avec la solution décrite dans le premier lien.
Si le fichier DpApi a une clé de machine statique définie dans Web.config, tous les ordinateurs du serveur seront en mesure de décrypter les données cryptées créées par un autre ordinateur de votre parc Web.
(code comme indiqué dans le modèle standard - de AccountController.cs)
private UserManager userManager;
public UserManager UserManager
{
get { return userManager ?? HttpContext.GetOwinContext().GetUserManager<UserManager>(); }
private set { userManager = value; }
}