Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

c# IUserTwoFactorProvider

Pagina: 1
Acties:

  • kevinkrs
  • Registratie: Juni 2010
  • Laatst online: 21-11 11:52
Hallo allemaal,

Ik probeer met asp.net mvc een two factor login maken, tevens probeer ik ook een wachtwoord vergeten service werkend te krijgen.

Ik maak gebruik van Ninject, hoe dan ook valt het mij op dat de ApplicationUserManager altijd de default is. En niet de aangepaste. Hierdoor wil IUserTwoFactorProvider maar niet geregistreerd worden en krijg ik de volgende fout

"No IUserTwoFactorProvider for 'EmailCode' is registered."

Weet iemand misschien wat ik fout gedaan hebt?

C#: IdentityConfig.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 /// <summary>
    /// The application user manager.
    /// </summary>
    public class ApplicationUserManager : UserManager<Account>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationUserManager"/> class.
        /// </summary>
        /// <param name="store">
        /// The store.
        /// </param>
        public ApplicationUserManager(IUserStore<Account> store)
            : base(store)
        {
        }

        /// <summary>
        /// The create.
        /// </summary>
        /// <param name="options">
        /// The options.
        /// </param>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <returns>
        /// The <see cref="ApplicationUserManager"/>.
        /// </returns>
        public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
        {
            var manager = new ApplicationUserManager(new UserStore<Account>());

            // Configure validation logic for usernames
            manager.UserValidator = new UserValidator<Account>(manager)
                                        {
                                            AllowOnlyAlphanumericUserNames = false,
                                            RequireUniqueEmail = true
                                        };

            // Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator
                                            {
                                                RequiredLength = 6,
                                                RequireNonLetterOrDigit = true,
                                                RequireDigit = true,
                                                RequireLowercase = true,
                                                RequireUppercase = true,
                                            };

            // Configure user lockout defaults
            manager.UserLockoutEnabledByDefault = true;
            manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
            manager.MaxFailedAccessAttemptsBeforeLockout = 5;

            // Register two factor authentication providers. This application uses 
            // Phone and Emails as a step of receiving a code for verifying 
            // the user You can write your own provider and plug in here.
            manager.RegisterTwoFactorProvider(
                "PhoneCode",
                new PhoneNumberTokenProvider<Account> { MessageFormat = "Your security code is: {0}" });

            manager.RegisterTwoFactorProvider(
                "EmailCode",
                new EmailTokenProvider<Account> { Subject = "SecurityCode", BodyFormat = "Your security code is {0}" });


            manager.EmailService = new EmailService();
            //manager.SmsService = new SmsService();
            var dataProtectionProvider = options.DataProtectionProvider;
            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider =
                    new DataProtectorTokenProvider<Account>(dataProtectionProvider.Create("ASP.NET Identity"));
            }

            return manager;
        }
    }


C#: Startup.Auth.cs
1
2
3
4
5
6
7
8
9
10
11
12
        public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

            // 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
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Management/Account/Login")
            });
        }


C#: UserManagerModule.cs
1
2
3
4
5
6
7
8
9
10
11
  public class UserManagerModule : NinjectModule
    {
        /// <summary>
        /// The load.
        /// </summary>
        public override void Load()
        {
            Kernel.Bind<ApplicationUserManager>().ToSelf()
            .InRequestScope().WithConstructorArgument("context", context => Kernel.Get<MyDbContext>());
        }
    }


C#: AccountController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  [HttpPost]
        public ActionResult ForgotPassword(AccountLostPasswordViewModel model)
        {
            var user = this.userManager.FindByName(model.UserName);

            if (user == null)
            {
                ModelState.AddModelError(string.Empty, "Gebruikersnaam bestaat niet");

                return this.View(model);
            }

            // Hier staat dat IUserTwoFactorProvider niet geregistreerd is...
            this.userManager.GenerateTwoFactorToken(user.Id, "EmailCode");

            return this.View(model);
        }

Verwijderd

Je registreert de Create van je ApplicationUserManager per Owin context, dat is goed, maar dan haal je vervolgens een nieuwe, niet-geconfigureerde, uit NInject (via de constructor van AccountController neem ik aan).

Maak daarom een property in AccountController en gebruik die:

C#:
1
2
3
4
private ApplicationUserManager UserManager
{
    get { return Request.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
}


Die geeft per Owin context dezelfde instantie van ApplicationUserManager terug, die je geconfigureerd geregistreerd hebt in ConfigureAuth.

  • kevinkrs
  • Registratie: Juni 2010
  • Laatst online: 21-11 11:52
Dankje voor je reactie.

Een property maken werkt inderdaad. Ik zie dat mijn settings aanwezig zijn in de manager. maar ik krijg ook per-direct een exception dat als volgt luid.

code:
1
2
3
An exception of type 'System.InvalidOperationException' occurred in mscorlib.dll but was not handled in user code

Additional information: The entity type Account is not part of the model for the current context.


Kun je me ook nog uitleggen hoe dat werkt met dependency injection, als bijvoorbeeld Ninject. Betekend dit dat je usermanager niet meer hoeft te injecten? Of moet je ze beiden gebruiken?

Alvast bedankt!

Verwijderd

Dit heeft ermee te maken dat je Account class dus geen onderdeel is van de Entity Framework context waar je mee werkt. Dit is op te lossen met configuratie van je context en/of de juiste structuur voor ASP.NET Identity.

Kortste klap is trouwens inheriten van IdentityDbContext<Account> waarbij je Account class weer inherit van IdentityUser.

  • kevinkrs
  • Registratie: Juni 2010
  • Laatst online: 21-11 11:52
Bedankt voor je reactie. Echter heb ik dat al. Dus het probleem moet ergens anders aan liggen.

Ik gok dat het komt omdat mijn dbconnecties injected worden door Ninject. En dat er nu een methode aangeroepen wordt dat niet geinjecteerd wordt (en dus ook op een andere context draait)

[ Voor 50% gewijzigd door kevinkrs op 07-07-2014 20:24 ]


Verwijderd

Ah, geef eens je MyDbContext mee in de constructor van UserStore<> op regel 31 van je ApplicationUserManager.

  • kevinkrs
  • Registratie: Juni 2010
  • Laatst online: 21-11 11:52
Geweldig, geen foutmelding meer! Nu is het wel zo dat ik new MyDbContext heb gebruikt. Ik weet niet of dat het erg is, want ik vermoed dat er dan twee requests geopend worden ipv 1. Kan dat kloppen of is dit juist prima zo en en worden de requests samengevoegd?
Pagina: 1