1 // Copyright (c) .NET Foundation. All rights reserved.
2 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3 
4 using System;
5 using System.Linq;
6 using System.Threading.Tasks;
7 using Identity.DefaultUI.WebSite;
8 using Microsoft.EntityFrameworkCore;
9 using Microsoft.Extensions.DependencyInjection;
10 using Xunit;
11 using Xunit.Sdk;
12 
13 namespace Microsoft.AspNetCore.Identity.FunctionalTests
14 {
15     public abstract class LoginTests<TStartup, TContext> : IClassFixture<ServerFactory<TStartup, TContext>>
16         where TStartup : class
17         where TContext : DbContext
18     {
LoginTests(ServerFactory<TStartup, TContext> serverFactory)19         public LoginTests(ServerFactory<TStartup, TContext> serverFactory)
20         {
21             ServerFactory = serverFactory;
22         }
23 
24         public ServerFactory<TStartup, TContext> ServerFactory { get; }
25 
26         [Fact]
CanLogInWithAPreviouslyRegisteredUser()27         public async Task CanLogInWithAPreviouslyRegisteredUser()
28         {
29             // Arrange
30             var client = ServerFactory.CreateClient();
31             var newClient = ServerFactory.CreateClient();
32 
33             var userName = $"{Guid.NewGuid()}@example.com";
34             var password = $"!Test.Password1$";
35 
36             // Act & Assert
37             await UserStories.RegisterNewUserAsync(client, userName, password);
38 
39             // Use a new client to simulate a new browser session.
40             await UserStories.LoginExistingUserAsync(newClient, userName, password);
41         }
42 
43         [Fact]
CanLogInWithAPreviouslyRegisteredUser_WithGlobalAuthorizeFilter()44         public async Task CanLogInWithAPreviouslyRegisteredUser_WithGlobalAuthorizeFilter()
45         {
46             // Arrange
47             void ConfigureTestServices(IServiceCollection services) =>
48                 services.SetupGlobalAuthorizeFilter();
49 
50             var server = ServerFactory
51                 .WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
52 
53             var client = server.CreateClient();
54             var newClient = server.CreateClient();
55 
56             var userName = $"{Guid.NewGuid()}@example.com";
57             var password = $"!Test.Password1$";
58 
59             // Act & Assert
60             await UserStories.RegisterNewUserAsync(client, userName, password);
61 
62             // Use a new client to simulate a new browser session.
63             await UserStories.LoginExistingUserAsync(newClient, userName, password);
64         }
65 
66         [Fact]
CanLogInWithTwoFactorAuthentication()67         public async Task CanLogInWithTwoFactorAuthentication()
68         {
69             // Arrange
70             var client = ServerFactory.CreateClient();
71             var newClient = ServerFactory.CreateClient();
72 
73             var userName = $"{Guid.NewGuid()}@example.com";
74             var password = $"!Test.Password1$";
75 
76             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
77             var showRecoveryCodes = await UserStories.EnableTwoFactorAuthentication(loggedIn);
78 
79             var twoFactorKey = showRecoveryCodes.Context.AuthenticatorKey;
80 
81             // Act & Assert
82             // Use a new client to simulate a new browser session.
83             await UserStories.LoginExistingUser2FaAsync(newClient, userName, password, twoFactorKey);
84         }
85 
86         [Fact]
CanLogInWithTwoFactorAuthentication_WithGlobalAuthorizeFilter()87         public async Task CanLogInWithTwoFactorAuthentication_WithGlobalAuthorizeFilter()
88         {
89             // Arrange
90             void ConfigureTestServices(IServiceCollection services) =>
91                 services.SetupGlobalAuthorizeFilter();
92 
93             var server = ServerFactory
94                 .WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
95 
96             var client = server.CreateClient();
97             var newClient = server.CreateClient();
98 
99             var userName = $"{Guid.NewGuid()}@example.com";
100             var password = $"!Test.Password1$";
101 
102             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
103             var showRecoveryCodes = await UserStories.EnableTwoFactorAuthentication(loggedIn);
104 
105             var twoFactorKey = showRecoveryCodes.Context.AuthenticatorKey;
106 
107             // Act & Assert
108             // Use a new client to simulate a new browser session.
109             await UserStories.LoginExistingUser2FaAsync(newClient, userName, password, twoFactorKey);
110         }
111 
112         [Fact]
CanLogInWithRecoveryCode()113         public async Task CanLogInWithRecoveryCode()
114         {
115             // Arrange
116             var client = ServerFactory.CreateClient();
117             var newClient = ServerFactory.CreateClient();
118 
119             var userName = $"{Guid.NewGuid()}@example.com";
120             var password = $"!Test.Password1$";
121 
122             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
123             var showRecoveryCodes = await UserStories.EnableTwoFactorAuthentication(loggedIn);
124 
125             var recoveryCode = showRecoveryCodes.Context.RecoveryCodes.First();
126 
127             // Act & Assert
128             // Use a new client to simulate a new browser session.
129             await UserStories.LoginExistingUserRecoveryCodeAsync(newClient, userName, password, recoveryCode);
130         }
131 
132         [Fact]
CanLogInWithRecoveryCode_WithGlobalAuthorizeFilter()133         public async Task CanLogInWithRecoveryCode_WithGlobalAuthorizeFilter()
134         {
135             // Arrange
136             void ConfigureTestServices(IServiceCollection services) =>
137                 services.SetupGlobalAuthorizeFilter();
138 
139             var server = ServerFactory
140                 .WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
141             var client = server.CreateClient();
142             var newClient = server.CreateClient();
143 
144             var userName = $"{Guid.NewGuid()}@example.com";
145             var password = $"!Test.Password1$";
146 
147             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
148             var showRecoveryCodes = await UserStories.EnableTwoFactorAuthentication(loggedIn);
149 
150             var recoveryCode = showRecoveryCodes.Context.RecoveryCodes.First();
151 
152             // Act & Assert
153             // Use a new client to simulate a new browser session.
154             await UserStories.LoginExistingUserRecoveryCodeAsync(newClient, userName, password, recoveryCode);
155         }
156 
157         [Fact]
CannotLogInWithoutRequiredEmailConfirmation()158         public async Task CannotLogInWithoutRequiredEmailConfirmation()
159         {
160             // Arrange
161             var emailSender = new ContosoEmailSender();
162             void ConfigureTestServices(IServiceCollection services) => services
163                     .SetupTestEmailSender(emailSender)
164                     .SetupEmailRequired();
165 
166             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
167 
168             var client = server.CreateClient();
169             var newClient = server.CreateClient();
170 
171             var userName = $"{Guid.NewGuid()}@example.com";
172             var password = $"!Test.Password1$";
173 
174             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
175 
176             // Act & Assert
177             // Use a new client to simulate a new browser session.
178             await Assert.ThrowsAnyAsync<XunitException>(() => UserStories.LoginExistingUserAsync(newClient, userName, password));
179         }
180 
181         [Fact]
CannotLogInWithoutRequiredEmailConfirmation_WithGlobalAuthorizeFilter()182         public async Task CannotLogInWithoutRequiredEmailConfirmation_WithGlobalAuthorizeFilter()
183         {
184             // Arrange
185             var emailSender = new ContosoEmailSender();
186             void ConfigureTestServices(IServiceCollection services) => services
187                     .SetupTestEmailSender(emailSender)
188                     .SetupEmailRequired()
189                     .SetupGlobalAuthorizeFilter();
190 
191             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
192 
193             var client = server.CreateClient();
194             var newClient = server.CreateClient();
195 
196             var userName = $"{Guid.NewGuid()}@example.com";
197             var password = $"!Test.Password1$";
198 
199             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
200 
201             // Act & Assert
202             // Use a new client to simulate a new browser session.
203             await Assert.ThrowsAnyAsync<XunitException>(() => UserStories.LoginExistingUserAsync(newClient, userName, password));
204         }
205 
206         [Fact]
CanLogInAfterConfirmingEmail()207         public async Task CanLogInAfterConfirmingEmail()
208         {
209             // Arrange
210             var emailSender = new ContosoEmailSender();
211             void ConfigureTestServices(IServiceCollection services) => services
212                 .SetupTestEmailSender(emailSender)
213                 .SetupEmailRequired();
214 
215             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
216 
217             var client = server.CreateClient();
218             var newClient = server.CreateClient();
219 
220             var userName = $"{Guid.NewGuid()}@example.com";
221             var password = $"!Test.Password1$";
222 
223             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
224 
225             // Act & Assert
226             // Use a new client to simulate a new browser session.
227             var email = Assert.Single(emailSender.SentEmails);
228             await UserStories.ConfirmEmailAsync(email, newClient);
229 
230             await UserStories.LoginExistingUserAsync(newClient, userName, password);
231         }
232 
233         [Fact]
CanLogInAfterConfirmingEmail_WithGlobalAuthorizeFilter()234         public async Task CanLogInAfterConfirmingEmail_WithGlobalAuthorizeFilter()
235         {
236             // Arrange
237             var emailSender = new ContosoEmailSender();
238             void ConfigureTestServices(IServiceCollection services) => services
239                 .SetupTestEmailSender(emailSender)
240                 .SetupEmailRequired()
241                 .SetupGlobalAuthorizeFilter();
242 
243             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
244 
245             var client = server.CreateClient();
246             var newClient = server.CreateClient();
247 
248             var userName = $"{Guid.NewGuid()}@example.com";
249             var password = $"!Test.Password1$";
250 
251             var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
252 
253             // Act & Assert
254             // Use a new client to simulate a new browser session.
255             var email = Assert.Single(emailSender.SentEmails);
256             await UserStories.ConfirmEmailAsync(email, newClient);
257 
258             await UserStories.LoginExistingUserAsync(newClient, userName, password);
259         }
260 
261         [Fact]
CanLoginWithASocialLoginProvider()262         public async Task CanLoginWithASocialLoginProvider()
263         {
264             // Arrange
265             void ConfigureTestServices(IServiceCollection services) =>
266                 services.SetupTestThirdPartyLogin();
267 
268             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
269 
270             var client = server.CreateClient();
271             var newClient = server.CreateClient();
272 
273             var guid = Guid.NewGuid();
274             var userName = $"{guid}";
275             var email = $"{guid}@example.com";
276 
277             // Act & Assert
278             await UserStories.RegisterNewUserWithSocialLoginAsync(client, userName, email);
279             await UserStories.LoginWithSocialLoginAsync(newClient, userName);
280         }
281 
282         [Fact]
CanLoginWithASocialLoginProvider_WithGlobalAuthorizeFilter()283         public async Task CanLoginWithASocialLoginProvider_WithGlobalAuthorizeFilter()
284         {
285             // Arrange
286             void ConfigureTestServices(IServiceCollection services) => services
287                 .SetupTestThirdPartyLogin()
288                 .SetupGlobalAuthorizeFilter();
289 
290             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
291 
292             var client = server.CreateClient();
293             var newClient = server.CreateClient();
294 
295             var guid = Guid.NewGuid();
296             var userName = $"{guid}";
297             var email = $"{guid}@example.com";
298 
299             // Act & Assert
300             await UserStories.RegisterNewUserWithSocialLoginAsync(client, userName, email);
301             await UserStories.LoginWithSocialLoginAsync(newClient, userName);
302         }
303 
304         [Fact]
CanLogInAfterResettingThePassword()305         public async Task CanLogInAfterResettingThePassword()
306         {
307             // Arrange
308             var emailSender = new ContosoEmailSender();
309             void ConfigureTestServices(IServiceCollection services) => services
310                 .SetupTestEmailSender(emailSender);
311 
312             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
313 
314             var client = server.CreateClient();
315             var resetPasswordClient = server.CreateClient();
316             var newClient = server.CreateClient();
317 
318             var userName = $"{Guid.NewGuid()}@example.com";
319             var password = $"!Test.Password1$";
320             var newPassword = $"!New.Password1$";
321 
322             await UserStories.RegisterNewUserAsync(client, userName, password);
323             var registrationEmail = Assert.Single(emailSender.SentEmails);
324             await UserStories.ConfirmEmailAsync(registrationEmail, client);
325 
326             // Act & Assert
327             await UserStories.ForgotPasswordAsync(resetPasswordClient, userName);
328             Assert.Equal(2, emailSender.SentEmails.Count);
329             var email = emailSender.SentEmails[1];
330             await UserStories.ResetPasswordAsync(resetPasswordClient, email, userName, newPassword);
331             await UserStories.LoginExistingUserAsync(newClient, userName, newPassword);
332         }
333 
334         [Fact]
CanResetPassword_WithGlobalAuthorizeFilter()335         public async Task CanResetPassword_WithGlobalAuthorizeFilter()
336         {
337             // Arrange
338             var emailSender = new ContosoEmailSender();
339             void ConfigureTestServices(IServiceCollection services) =>
340                 services.SetupGlobalAuthorizeFilter().SetupTestEmailSender(emailSender);
341 
342             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
343 
344             var client = server.CreateClient();
345             var resetPasswordClient = server.CreateClient();
346             var newClient = server.CreateClient();
347 
348             var userName = $"{Guid.NewGuid()}@example.com";
349             var password = $"!Test.Password1$";
350             var newPassword = $"!New.Password1$";
351 
352             await UserStories.RegisterNewUserAsync(client, userName, password);
353             var registrationEmail = Assert.Single(emailSender.SentEmails);
354             await UserStories.ConfirmEmailAsync(registrationEmail, client);
355 
356             // Act & Assert
357             await UserStories.ForgotPasswordAsync(resetPasswordClient, userName);
358             Assert.Equal(2, emailSender.SentEmails.Count);
359             var email = emailSender.SentEmails[1];
360             await UserStories.ResetPasswordAsync(resetPasswordClient, email, userName, newPassword);
361             await UserStories.LoginExistingUserAsync(newClient, userName, newPassword);
362         }
363 
364         [Fact]
UserNotLockedOut_AfterMaxFailedAccessAttempts_WithGlobalAuthorizeFilter()365         public async Task UserNotLockedOut_AfterMaxFailedAccessAttempts_WithGlobalAuthorizeFilter()
366         {
367             // Arrange
368             var emailSender = new ContosoEmailSender();
369             void ConfigureTestServices(IServiceCollection services) =>
370                 services.SetupGlobalAuthorizeFilter().SetupMaxFailedAccessAttempts().SetupTestEmailSender(emailSender);
371 
372             var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
373 
374             var client = server.CreateClient();
375             var newClient = server.CreateClient();
376 
377             var userName = $"{Guid.NewGuid()}@example.com";
378             var password = $"!Test.Password1$";
379             var wrongPassword = $"!Wrong.Password1$";
380 
381             await UserStories.RegisterNewUserAsync(client, userName, password);
382             var registrationEmail = Assert.Single(emailSender.SentEmails);
383             await UserStories.ConfirmEmailAsync(registrationEmail, client);
384 
385             // Act & Assert
386             await UserStories.LoginFailsWithWrongPasswordAsync(newClient, userName, wrongPassword);
387         }
388     }
389 }
390