Skip to content

Commit 506336e

Browse files
author
Daniel Jacinto
authored
[2FA] Update link msa/aad account page with legacy password account information. (#9408)
* Updated page to show legacy account information * email moved to first line. * let users link msa/aad account after being on exception list. * fix tests
1 parent fca6b87 commit 506336e

4 files changed

Lines changed: 83 additions & 18 deletions

File tree

src/NuGetGallery/Controllers/AuthenticationController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public virtual async Task<ActionResult> SignIn(LogOnViewModel model, string retu
137137
}
138138

139139
var authenticationResult = await _authService.Authenticate(model.SignIn.UserNameOrEmail, model.SignIn.Password);
140-
140+
141141
if (authenticationResult.Result != PasswordAuthenticationResult.AuthenticationResult.Success)
142142
{
143143
string modelErrorMessage = string.Empty;
@@ -936,7 +936,7 @@ private ActionResult AuthenticationView(string viewName, LogOnViewModel existing
936936
existingModel.SignIn = existingModel.SignIn ?? new SignInViewModel();
937937
existingModel.Register = existingModel.Register ?? new RegisterViewModel();
938938
existingModel.IsNuGetAccountPasswordLoginEnabled = _featureFlagService.IsNuGetAccountPasswordLoginEnabled();
939-
939+
existingModel.IsEmailOnExceptionList = _contentObjectService.LoginDiscontinuationConfiguration.IsEmailOnExceptionsList(existingModel.SignIn.UserNameOrEmail);
940940
return View(viewName, existingModel);
941941
}
942942

src/NuGetGallery/ViewModels/LogOnViewModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class LogOnViewModel
1616
public RegisterViewModel Register { get; set; }
1717
public IList<AuthenticationProviderViewModel> Providers { get; set; }
1818
public bool IsNuGetAccountPasswordLoginEnabled { get; set; }
19+
public bool IsEmailOnExceptionList { get; set; }
1920

2021
public LogOnViewModel()
2122
: this(new SignInViewModel())

src/NuGetGallery/Views/Authentication/LinkExternal.cshtml

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,49 @@
99
<section role="main" class="container main-container page-sign-in">
1010
@if (Model.External.FoundExistingUser)
1111
{
12-
<div class="row">
13-
<div class="col-xs-12">
14-
<h1 class="text-center">Link @Model.External.ProviderAccountNoun</h1>
15-
</div>
16-
</div>
1712
<div class="row">
1813
<div class="@ViewHelpers.GetColumnClasses(ViewBag)">
1914
@if (Model.External.ExistingUserCanBeLinked)
2015
{
21-
<p class="text-center">
22-
We found an account with this email address. Sign in with your NuGet.org password to link with this Microsoft account.
23-
</p>
24-
<p class="text-center">
25-
Note that <b>your existing password login will be disabled</b> and you will need to use this Microsoft account to sign into NuGet.org
26-
</p>
27-
<p class="text-center">
28-
Please <a href="mailto:@Config.Current.GalleryOwner.Address">contact support</a> if you need more assistance.
29-
</p>
16+
if (Model.IsEmailOnExceptionList)
17+
{
18+
<div class="row">
19+
<div class="col-xs-12">
20+
<h1 class="text-center">Link @Model.External.ProviderAccountNoun</h1>
21+
</div>
22+
</div>
23+
<p class="text-center">
24+
Sign in with your NuGet.org password to link with this Microsoft account.
25+
</p>
26+
<p class="text-center">
27+
Please <a href="mailto:@Config.Current.GalleryOwner.Address">contact support</a> if you need more assistance.
28+
</p>
3029

31-
@Html.Partial("_SignIn", Model)
30+
@Html.Partial("_SignIn", Model)
31+
}
32+
else
33+
{
34+
<div class="row">
35+
<div class="col-xs-12">
36+
<h1 class="text-center">Legacy Account</h1>
37+
</div>
38+
</div>
39+
<p class="text-center">
40+
We found an account with this email address (@Model.SignIn.UserNameOrEmail) that uses legacy password login. Unfortunately, <b>password login has been disabled</b>.
41+
</p>
42+
<p class="text-center">
43+
Some accounts can be recovered through manual proof of ownership.
44+
Please reach out to <a href="mailto:@Config.Current.GalleryOwner.Address">nuget support</a> for assistance.
45+
</p>
46+
}
3247
}
3348
else
3449
{
50+
<div class="row">
51+
<div class="col-xs-12">
52+
<h1 class="text-center">Link @Model.External.ProviderAccountNoun</h1>
53+
</div>
54+
</div>
3555
switch (Model.External.ExistingUserLinkingError)
3656
{
3757
case AssociateExternalAccountViewModel.ExistingUserLinkingErrorType.AccountIsAlreadyLinked:

tests/NuGetGallery.Facts/Controllers/AuthenticationControllerFacts.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ public class AuthenticationControllerFacts
3333

3434
public class TheLogOnAction : TestContainer
3535
{
36+
public TheLogOnAction()
37+
{
38+
var isEmailOnExceptionList = new Mock<ILoginDiscontinuationConfiguration>();
39+
isEmailOnExceptionList
40+
.Setup(x => x.IsEmailOnExceptionsList(It.IsAny<String>()))
41+
.Returns(false);
42+
GetMock<IContentObjectService>()
43+
.Setup(x => x.LoginDiscontinuationConfiguration)
44+
.Returns(isEmailOnExceptionList.Object);
45+
}
46+
3647
[Fact]
3748
public void GivenUserAlreadyAuthenticated_ItRedirectsToReturnUrl()
3849
{
@@ -215,6 +226,17 @@ public async Task SendsNotificationForAssistance()
215226

216227
public class TheSignInAction : TestContainer
217228
{
229+
public TheSignInAction()
230+
{
231+
var isEmailOnExceptionList = new Mock<ILoginDiscontinuationConfiguration>();
232+
isEmailOnExceptionList
233+
.Setup(x => x.IsEmailOnExceptionsList(It.IsAny<String>()))
234+
.Returns(false);
235+
GetMock<IContentObjectService>()
236+
.Setup(x => x.LoginDiscontinuationConfiguration)
237+
.Returns(isEmailOnExceptionList.Object);
238+
}
239+
218240
[Fact]
219241
public async Task GivenUserAlreadyAuthenticated_ItRedirectsToReturnUrl()
220242
{
@@ -722,6 +744,17 @@ public async Task GivenAdminLogsInWithValidExternalAuth_ItChallengesWhenNotUsing
722744

723745
public class TheRegisterAction : TestContainer
724746
{
747+
public TheRegisterAction()
748+
{
749+
var isEmailOnExceptionList = new Mock<ILoginDiscontinuationConfiguration>();
750+
isEmailOnExceptionList
751+
.Setup(x => x.IsEmailOnExceptionsList(It.IsAny<String>()))
752+
.Returns(false);
753+
GetMock<IContentObjectService>()
754+
.Setup(x => x.LoginDiscontinuationConfiguration)
755+
.Returns(isEmailOnExceptionList.Object);
756+
}
757+
725758
[Fact]
726759
public async Task WillShowTheViewWithErrorsIfTheModelStateIsInvalid()
727760
{
@@ -1726,6 +1759,17 @@ public void WillRedirectToHomePageOnSuccessForAbsoluteUrls()
17261759

17271760
public class TheLinkExternalAccountAction : TestContainer
17281761
{
1762+
public TheLinkExternalAccountAction()
1763+
{
1764+
var isEmailOnExceptionList = new Mock<ILoginDiscontinuationConfiguration>();
1765+
isEmailOnExceptionList
1766+
.Setup(x => x.IsEmailOnExceptionsList(It.IsAny<String>()))
1767+
.Returns(false);
1768+
GetMock<IContentObjectService>()
1769+
.Setup(x => x.LoginDiscontinuationConfiguration)
1770+
.Returns(isEmailOnExceptionList.Object);
1771+
}
1772+
17291773
[Theory]
17301774
[InlineData("access_denied")]
17311775
[InlineData("consent_required")]
@@ -2219,7 +2263,7 @@ public async Task GivenNoLinkAndEmailClaim_ItDisplaysLogOnViewWithEmailPrefilled
22192263
var msAuther = new MicrosoftAccountAuthenticator();
22202264
var msaUI = msAuther.GetUI();
22212265

2222-
GetMock<AuthenticationService>(); // Force a mock to be created
2266+
GetMock<AuthenticationService>(); // Force a mock to be created
22232267

22242268
var controller = GetController<AuthenticationController>();
22252269

0 commit comments

Comments
 (0)