Commit c1248b8a authored by Michael Adams's avatar Michael Adams

Attempt to better indicate failures

parent 58058e74
......@@ -2,7 +2,8 @@ export class Alerts {
errorAlertBody: string;
errorAlertTitle: string;
errorInvalidCredentials: string;
errorPasswordChangeNotAllowed :string;
errorInvalidDomain: string;
errorPasswordChangeNotAllowed: string;
successAlertBody: string;
successAlertTitle: string;
}
\ No newline at end of file
......@@ -66,7 +66,8 @@ namespace Unosquare.PassCore.Web.Controllers
// Validate the Captcha
try
{
if (await ValidateRecaptcha(model.Recaptcha)== false)
// Sonar-Codacy suggested ConfigureAwait
if (await ValidateRecaptcha(model.Recaptcha).ConfigureAwait(false) == false)
{
result.Errors.Add(new ApiErrorItem
{
......
......@@ -3,9 +3,7 @@
using System.Collections.Generic;
using Unosquare.PassCore.Web.Models;
// Codacy kept thinking the original implementation was an issue.
// https://stackoverflow.com/questions/9415257/how-can-i-implement-static-methods-on-an-interface
// Sonar-Codacy thought we needed a static method here; and suggested dual default nulls was pointless.
internal class DebugPasswordChangeProvider : IPasswordChangeProvider
{
static ApiErrorItem PerformPasswordChange(ChangePasswordModel model)
......
......@@ -32,44 +32,47 @@ namespace Unosquare.PassCore.Web.Helpers
// Check if password change is allowed
if (userPrincipal.UserCannotChangePassword)
{
throw new ArgumentOutOfRangeException(_options.ClientSettings.Alerts.ErrorPasswordChangeNotAllowed);
return new ApiErrorItem { ErrorType = ApiErrorType.GeneralFailure, ErrorCode = ApiErrorCode.ChangeNotPermitted, Message = _options.ClientSettings.Alerts.ErrorPasswordChangeNotAllowed };
}
// Validate user credentials
if (principalContext.ValidateCredentials(model.Username, model.CurrentPassword) == false)
{
// Your new authenticate code snippet
// Check for default domain: if none given, ensure EFLD can be used as an override.
var token = IntPtr.Zero;
try
{
var parts = userPrincipal.UserPrincipalName.Split(new[] { '@' }, StringSplitOptions.RemoveEmptyEntries);
// Check for default domain, if none given
var domain = _options.ClientSettings.DefaultDomain ?? (parts.Length > 1 ? parts[1] : null);
var parts = userPrincipal.UserPrincipalName.Split(new[] { '@' }, StringSplitOptions.RemoveEmptyEntries);
string emailFormatLogonDomain = (parts.Length > 1 ? parts[1] : null);
string defaultDomain = _options.ClientSettings.DefaultDomain;
string domain = "";
if (domain == null)
{
throw new ArgumentOutOfRangeException(_options.ClientSettings.Alerts.ErrorInvalidCredentials);
}
// Domain-determinance
if (String.IsNullOrEmpty(emailFormatLogonDomain) && String.IsNullOrEmpty(defaultDomain))
{
return new ApiErrorItem { ErrorType = ApiErrorType.GeneralFailure, ErrorCode = ApiErrorCode.InvalidDomain, Message = _options.ClientSettings.Alerts.ErrorInvalidDomain };
}
else if(String.IsNullOrEmpty(defaultDomain))
{
domain = emailFormatLogonDomain;
}
else
{
domain = defaultDomain;
}
if (!LogonUser(model.Username, domain, model.CurrentPassword, LogonTypes.Network, LogonProviders.Default, out token))
if (!LogonUser(model.Username, domain, model.CurrentPassword, LogonTypes.Network, LogonProviders.Default, out token))
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
switch (errorCode)
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
switch (errorCode)
{
case ERROR_PASSWORD_MUST_CHANGE:
case ERROR_PASSWORD_EXPIRED:
// Both of these means that the password CAN change and that we got the correct password
break;
default:
throw new ArgumentOutOfRangeException(_options.ClientSettings.Alerts.ErrorInvalidCredentials);
}
case ERROR_PASSWORD_MUST_CHANGE:
case ERROR_PASSWORD_EXPIRED:
// Both of these means that the password CAN change and that we got the correct password
break;
default:
return new ApiErrorItem { ErrorType = ApiErrorType.GeneralFailure, ErrorCode = ApiErrorCode.InvalidCredentials, Message = _options.ClientSettings.Alerts.ErrorInvalidCredentials };
}
}
finally
{
CloseHandle(token);
}
}
// Verify user is not a member of an excluded group
......@@ -79,7 +82,7 @@ namespace Unosquare.PassCore.Web.Helpers
{
if (_options.ClientSettings.RestrictedADGroups.Contains(userPrincipalAuthGroup.Name))
{
throw new Exception(_options.ClientSettings.Alerts.ErrorPasswordChangeNotAllowed);
return new ApiErrorItem { ErrorType = ApiErrorType.GeneralFailure, ErrorCode = ApiErrorCode.ChangeNotPermitted, Message = _options.ClientSettings.Alerts.ErrorPasswordChangeNotAllowed };
}
}
}
......
......@@ -21,6 +21,8 @@ namespace Unosquare.PassCore.Web.Models
UserNotFound = 3,
InvalidCredentials = 4,
InvalidCaptcha = 5,
ChangeNotPermitted = 6,
InvalidDomain = 7
}
/// <summary>
......
......@@ -8,72 +8,73 @@ namespace Unosquare.PassCore.Web.Models
public class AppSettings
{
public bool EnableHttpsRedirect { get; set; } = true;
public string RecaptchaPrivateKey { get; set; }
public PasswordChangeOptions PasswordChangeOptions { get; set; }
public ClientSettings ClientSettings { get; set; }
public PasswordChangeOptions PasswordChangeOptions { get; set; }
public string RecaptchaPrivateKey { get; set; }
}
public class PasswordChangeOptions
{
public bool UseAutomaticContext { get; set; } = true;
public string LdapHostname { get; set; }
public int LdapPort { get; set; } = 389;
public string LdapUsername { get; set; }
public string LdapHostname { get; set; }
public string LdapPassword { get; set; }
public string LdapUsername { get; set; }
}
public class ClientSettings
{
public string ApplicationTitle { get; set; }
public string ChangePasswordTitle { get; set; }
public ChangePasswordForm ChangePasswordForm { get; set; }
public string DefaultDomain { get; set; }
public List<string> ErrorMessages { get; set; }
public ErrorsPasswordForm ErrorsPasswordForm { get; set; }
public Recaptcha Recaptcha { get; set; }
public bool ShowPasswordMeter { get; set; }
public Alerts Alerts { get; set; }
public bool CheckRestrictedAdGroups { get; set; }
public bool ShowPasswordMeter { get; set; }
public ChangePasswordForm ChangePasswordForm { get; set; }
public ErrorsPasswordForm ErrorsPasswordForm { get; set; }
public List<string> ErrorMessages { get; set; }
public List<string> RestrictedADGroups { get; set; }
public Recaptcha Recaptcha { get; set; }
public string ApplicationTitle { get; set; }
public string ChangePasswordTitle { get; set; }
public string DefaultDomain { get; set; }
}
public class ChangePasswordForm
{
public string HelpTitle { get; set; }
public string HelpText { get; set; }
public string UsernameLabel { get; set; }
public string UsernameHelpblock { get; set; }
public string CurrentPasswordLabel { get; set; }
public string ChangePasswordButtonLabel { get; set; }
public string CurrentPasswordHelpblock { get; set; }
public string NewPasswordLabel { get; set; }
public string CurrentPasswordLabel { get; set; }
public string HelpText { get; set; }
public string HelpTitle { get; set; }
public string NewPasswordHelpblock { get; set; }
public string NewPasswordVerifyLabel { get; set; }
public string NewPasswordLabel { get; set; }
public string NewPasswordVerifyHelpblock { get; set; }
public string ChangePasswordButtonLabel { get; set; }
public string NewPasswordVerifyLabel { get; set; }
public string UsernameHelpblock { get; set; }
public string UsernameLabel { get; set; }
}
public class Recaptcha
{
public bool IsEnabled { get; set; }
public string SiteKey { get; set; }
public string LanguageCode { get; set; }
public string SiteKey { get; set; }
}
public class Alerts
{
public string SuccessAlertTitle { get; set; }
public string SuccessAlertBody { get; set; }
public string ErrorAlertTitle { get; set; }
public string ErrorAlertBody { get; set; }
public string ErrorPasswordChangeNotAllowed { get; set; }
public string ErrorAlertTitle { get; set; }
public string ErrorInvalidCredentials { get; set; }
public string ErrorInvalidDomain {get; set; }
public string ErrorPasswordChangeNotAllowed { get; set; }
public string SuccessAlertBody { get; set; }
public string SuccessAlertTitle { get; set; }
}
public class ErrorsPasswordForm
{
public string FieldRequired { get; set; }
public string UsernamePattern { get; set; }
public string UsernameEmailPattern { get; set; }
public string PasswordMatch { get; set; }
public string UsernameEmailPattern { get; set; }
public string UsernamePattern { get; set; }
}
}
\ No newline at end of file
......@@ -59,7 +59,9 @@
"Fields don't match",
"We could not find your user account",
"The username and current password you provided are invalid",
"Could not verify you are not a robot"
"Could not verify you are not a robot",
"Password change is not permitted",
"Invalid Domain"
],
"Alerts": {
"SuccessAlertTitle": "You have changed your password successfully.",
......@@ -67,7 +69,8 @@
"ErrorAlertTitle": "There was an error changing your password",
"ErrorAlertBody": "Error Information: ",
"ErrorPasswordChangeNotAllowed": "You are not allowed to change your password. Please contact your system administrator.",
"ErrorInvalidCredentials": "You need to provide the correct current password."
"ErrorInvalidCredentials": "You need to provide the correct current password.",
"ErrorInvalidDomain": "You have supplied an invalid domain to logon to."
}
}
}
......
......@@ -60,6 +60,11 @@
- https://www.npmjs.com/package/@ngtools/webpack
- https://www.npmjs.com/package/angular-named-lazy-chunks-webpack-plugin
## Sonar / Codacy fix suggestions
- https://medium.com/bynder-tech/c-why-you-should-use-configureawait-false-in-your-library-code-d7837dce3d7f
- https://stackoverflow.com/questions/9415257/how-can-i-implement-static-methods-on-an-interface
## Brotli (if interested in using for smaller delivery)
- https://blogs.msdn.microsoft.com/dotnet/2017/07/27/introducing-support-for-brotli-compression/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment