|
22 | 22 |
|
23 | 23 | namespace NuGetGallery |
24 | 24 | { |
| 25 | + public static class AuthenticationFailureErrors |
| 26 | + { |
| 27 | + public const string ACCESSS_DENIED = "access_denied"; |
| 28 | + public const string CONSENT_REQUIRED = "consent_required"; |
| 29 | + } |
| 30 | + |
25 | 31 | public partial class AuthenticationController |
26 | 32 | : AppController |
27 | 33 | { |
@@ -172,7 +178,7 @@ public virtual async Task<ActionResult> SignIn(LogOnViewModel model, string retu |
172 | 178 | authenticatedUser = loginUserDetails?.AuthenticatedUser; |
173 | 179 | if (authenticatedUser == null) |
174 | 180 | { |
175 | | - return ExternalLinkExpired(); |
| 181 | + return AuthenticationFailureOrExternalLinkExpired(); |
176 | 182 | } |
177 | 183 |
|
178 | 184 | usedMultiFactorAuthentication = loginUserDetails.UsedMultiFactorAuthentication; |
@@ -264,7 +270,7 @@ public virtual async Task<ActionResult> Register(LogOnViewModel model, string re |
264 | 270 | var result = await _authService.ReadExternalLoginCredential(OwinContext); |
265 | 271 | if (result.ExternalIdentity == null) |
266 | 272 | { |
267 | | - return ExternalLinkExpired(); |
| 273 | + return AuthenticationFailureOrExternalLinkExpired(); |
268 | 274 | } |
269 | 275 |
|
270 | 276 | usedMultiFactorAuthentication = result.LoginDetails?.WasMultiFactorAuthenticated ?? false; |
@@ -497,15 +503,16 @@ public virtual async Task<ActionResult> LinkOrChangeExternalCredential(string re |
497 | 503 | return SafeRedirect(returnUrl); |
498 | 504 | } |
499 | 505 |
|
500 | | - public virtual async Task<ActionResult> LinkExternalAccount(string returnUrl) |
| 506 | + public virtual async Task<ActionResult> LinkExternalAccount(string returnUrl, string error = null, string errorDescription = null) |
501 | 507 | { |
502 | 508 | // Extract the external login info |
503 | 509 | var result = await _authService.AuthenticateExternalLogin(OwinContext); |
504 | 510 | if (result.ExternalIdentity == null) |
505 | 511 | { |
506 | 512 | // User got here without an external login cookie (or an expired one) |
507 | 513 | // Send them to the logon action |
508 | | - return ExternalLinkExpired(); |
| 514 | + string errorMessage = GetAuthenticationFailureMessage(error, errorDescription); |
| 515 | + return AuthenticationFailureOrExternalLinkExpired(errorMessage); |
509 | 516 | } |
510 | 517 |
|
511 | 518 | if (result.Authentication != null) |
@@ -749,11 +756,11 @@ private string GetEmailAddressFromExternalLoginResult(AuthenticateExternalLoginR |
749 | 756 | } |
750 | 757 | } |
751 | 758 |
|
752 | | - private ActionResult ExternalLinkExpired() |
| 759 | + private ActionResult AuthenticationFailureOrExternalLinkExpired(string errorMessage = null) |
753 | 760 | { |
754 | 761 | // User got here without an external login cookie (or an expired one) |
755 | 762 | // Send them to the logon action with a message |
756 | | - TempData["Message"] = Strings.ExternalAccountLinkExpired; |
| 763 | + TempData["Message"] = string.IsNullOrEmpty(errorMessage) ? Strings.ExternalAccountLinkExpired : errorMessage; |
757 | 764 | return Redirect(Url.LogOn(null, relativeUrl: false)); |
758 | 765 | } |
759 | 766 |
|
@@ -815,5 +822,24 @@ private ActionResult AuthenticationView(string viewName, LogOnViewModel existing |
815 | 822 |
|
816 | 823 | return View(viewName, existingModel); |
817 | 824 | } |
| 825 | + |
| 826 | + private string GetAuthenticationFailureMessage(string error, string errorDescription) |
| 827 | + { |
| 828 | + if (string.IsNullOrEmpty(error)) |
| 829 | + { |
| 830 | + return Strings.AuthenticationFailure_UnkownError; |
| 831 | + } |
| 832 | + |
| 833 | + switch (error) |
| 834 | + { |
| 835 | + case AuthenticationFailureErrors.ACCESSS_DENIED: |
| 836 | + case AuthenticationFailureErrors.CONSENT_REQUIRED: |
| 837 | + return Strings.ExternalAccountLinkExpired; |
| 838 | + default: |
| 839 | + return string.IsNullOrEmpty(errorDescription) |
| 840 | + ? error |
| 841 | + : errorDescription; |
| 842 | + } |
| 843 | + } |
818 | 844 | } |
819 | 845 | } |
0 commit comments