Exemple #1
0
        public SignUpResult SignUp(string name, string credentialTypeCode, string identifier, string secret)
        {
            Users user = new Users();

            user.Name    = name;
            user.Created = DateTime.Now.ToShortDateString();
            this._context.Users.Add(user);
            this._context.SaveChanges();

            CredentialTypes credentialType = this._context.CredentialTypes.FirstOrDefault(ct => string.Equals(ct.Code, credentialTypeCode, StringComparison.OrdinalIgnoreCase));

            if (credentialType == null)
            {
                return(new SignUpResult(success: false, error: SignUpResultError.CredentialTypeNotFound));
            }

            Credentials credential = new Credentials();

            credential.UserId           = user.Id;
            credential.CredentialTypeId = credentialType.Id;
            credential.Identifier       = identifier;

            if (!string.IsNullOrEmpty(secret))
            {
                byte[] salt = Pbkdf2Hasher.GenerateRandomSalt();
                string hash = Pbkdf2Hasher.ComputeHash(secret, salt);

                credential.Secret = hash;
                credential.Extra  = Convert.ToBase64String(salt);
            }

            this._context.Credentials.Add(credential);
            this._context.SaveChanges();
            return(new SignUpResult(user: user, success: true));
        }
Exemple #2
0
        /// <summary>
        /// On subscribe, set API keys with push capability to expire in <see cref="PushKeysExpirationInDays" /> days.
        /// </summary>
        /// <param name="context"></param>
        public async Task OnSubscribeAsync(UserSecurityPolicySubscriptionContext context)
        {
            var pushKeys = context.User.Credentials.Where(c =>
                                                          CredentialTypes.IsApiKey(c.Type) &&
                                                          (
                                                              c.Scopes.Count == 0 ||
                                                              c.Scopes.Any(s =>
                                                                           s.AllowedAction.Equals(NuGetScopes.PackagePush, StringComparison.OrdinalIgnoreCase) ||
                                                                           s.AllowedAction.Equals(NuGetScopes.PackagePushVersion, StringComparison.OrdinalIgnoreCase)
                                                                           ))
                                                          );

            var expires     = DateTime.UtcNow.AddDays(PushKeysExpirationInDays);
            var expireTasks = new List <Task>();

            foreach (var key in pushKeys)
            {
                if (!key.Expires.HasValue || key.Expires > expires)
                {
                    expireTasks.Add(_auditing.SaveAuditRecordAsync(
                                        new UserAuditRecord(context.User, AuditedUserAction.ExpireCredential, key)));

                    key.Expires = expires;
                }
            }
            await Task.WhenAll(expireTasks);

            _diagnostics.Information($"Expiring {pushKeys.Count()} keys with push capability for user '{context.User.Username}'.");
        }
Exemple #3
0
        public ValidateResult Validate(string credentialTypeCode, string identifier, string secret)
        {
            CredentialTypes credentialType = this._context.CredentialTypes.FirstOrDefault(ct => string.Equals(ct.Code, credentialTypeCode, StringComparison.OrdinalIgnoreCase));

            if (credentialType == null)
            {
                return(new ValidateResult(success: false, error: ValidateResultError.CredentialTypeNotFound));
            }

            Credentials credential = this._context.Credentials.FirstOrDefault(c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);

            if (credential == null)
            {
                return(new ValidateResult(success: false, error: ValidateResultError.CredentialNotFound));
            }

            if (!string.IsNullOrEmpty(secret))
            {
                byte[] salt = Convert.FromBase64String(credential.Extra);
                string hash = Pbkdf2Hasher.ComputeHash(secret, salt);

                if (credential.Secret != hash)
                {
                    return(new ValidateResult(success: false, error: ValidateResultError.SecretNotValid));
                }
            }

            return(new ValidateResult(user: this._context.Users.Find(credential.UserId), success: true));
        }
Exemple #4
0
        public ChangeSecretResult ChangeSecret(string credentialTypeCode, string identifier, string secret)
        {
            CredentialTypes credentialType = this._context.CredentialTypes.FirstOrDefault(ct => string.Equals(ct.Code, credentialTypeCode, StringComparison.OrdinalIgnoreCase));

            if (credentialType == null)
            {
                return(new ChangeSecretResult(success: false, error: ChangeSecretResultError.CredentialTypeNotFound));
            }

            Credentials credential = this._context.Credentials.FirstOrDefault(c => c.CredentialTypeId == credentialType.Id && c.Identifier == identifier);

            if (credential == null)
            {
                return(new ChangeSecretResult(success: false, error: ChangeSecretResultError.CredentialNotFound));
            }

            byte[] salt = Pbkdf2Hasher.GenerateRandomSalt();
            string hash = Pbkdf2Hasher.ComputeHash(secret, salt);

            credential.Secret = hash;
            credential.Extra  = Convert.ToBase64String(salt);
            this._context.Credentials.Update(credential);
            this._context.SaveChanges();
            return(new ChangeSecretResult(success: true));
        }
        public CredentialAuditRecord(Credential credential, bool removed)
        {
            if (credential == null)
            {
                throw new ArgumentNullException(nameof(credential));
            }

            Key         = credential.Key;
            Type        = credential.Type;
            Description = credential.Description;
            Identity    = credential.Identity;

            // Track the value for credentials that are definitely revocable (API Key, etc.) and have been removed
            if (removed && !CredentialTypes.IsPassword(credential.Type))
            {
                Value = credential.Value;
            }
            Created  = credential.Created;
            Expires  = credential.Expires;
            LastUsed = credential.LastUsed;

            // Track scopes
            Scopes = new List <ScopeAuditRecord>();
            foreach (var scope in credential.Scopes)
            {
                Scopes.Add(new ScopeAuditRecord(scope.Subject, scope.AllowedAction));
            }
        }
Exemple #6
0
        public CredentialState GetCredentialState(BiometricIdentity identity, CredentialTypes credentialType)
        {
            if (identity == null)
            {
                throw new ArgumentNullException(nameof(identity));
            }

            return(WinBiometric.GetCredentialState(identity, credentialType));
        }
Exemple #7
0
        public CredentialAuditRecord(Credential credential, bool removed)
        {
            Type     = credential.Type;
            Identity = credential.Ident;

            // Track the value for credentials that are definitely revokable (API Key, etc.) and have been removed
            if (removed && !CredentialTypes.IsPassword(credential.Type))
            {
                Value = credential.Value;
            }
        }
Exemple #8
0
 private static CredentialKind GetCredentialKind(string type)
 {
     if (CredentialTypes.IsApiKey(type))
     {
         return(CredentialKind.Token);
     }
     else if (CredentialTypes.IsPassword(type))
     {
         return(CredentialKind.Password);
     }
     return(CredentialKind.External);
 }
        public CredentialAuditRecord(Credential credential, bool removed)
        {
            Key      = credential.Key;
            Type     = credential.Type;
            Identity = credential.Identity;

            // Track the value for credentials that are definitely revocable (API Key, etc.) and have been removed
            if (removed && !CredentialTypes.IsPassword(credential.Type))
            {
                Value = credential.Value;
            }
            Created  = credential.Created;
            Expires  = credential.Expires;
            LastUsed = credential.LastUsed;
        }
Exemple #10
0
        private bool IsRevocable(ApiKeyViewModel apiKeyViewModel)
        {
            if (apiKeyViewModel == null)
            {
                return(false);
            }
            if (apiKeyViewModel.HasExpired)
            {
                return(false);
            }
            if (!CredentialTypes.IsApiKey(apiKeyViewModel.Type))
            {
                return(false);
            }

            return(true);
        }
        // Returns the set of credential types supported by this store for the specified principal.
        // Used when an application tries to access the PasswordInfo property of a newly-inserted
        // (not yet persisted) AuthenticablePrincipal, to determine whether it should be allowed.
        // Also used to implement AuthenticablePrincipal.SupportedCredentialTypes.
        internal override CredentialTypes SupportedCredTypes(AuthenticablePrincipal p)
        {
            // Fake principals do not have store objects, so they certainly don't have stored creds.
            if (p.fakePrincipal)
            {
                return((CredentialTypes)0);
            }

            CredentialTypes supportedTypes = CredentialTypes.Password;

            // Longhorn SAM supports certificate-based authentication
            if (this.IsLSAM)
            {
                supportedTypes |= CredentialTypes.Certificate;
            }

            return(supportedTypes);
        }
Exemple #12
0
        public bool IsActiveApiKeyCredential(Credential credential)
        {
            if (credential == null)
            {
                return(false);
            }
            if (!CredentialTypes.IsApiKey(credential.Type))
            {
                return(false);
            }
            if (IsCredentialExpiredOrNonScopedApiKeyNotUsedInLastDays(credential))
            {
                return(false);
            }
            if (credential.RevocationSourceKey != null)
            {
                return(false);
            }

            return(true);
        }
        public virtual async Task <PasswordAuthenticationResult> Authenticate(string userNameOrEmail, string password)
        {
            using (_trace.Activity("Authenticate:" + userNameOrEmail))
            {
                var user = FindByUserNameOrEmail(userNameOrEmail);

                // Check if the user exists
                if (user == null)
                {
                    _trace.Information("No such user: "******"Login failed. User account {userNameOrEmail} is locked for the next {remainingMinutes} minutes.");

                    return(new PasswordAuthenticationResult(PasswordAuthenticationResult.AuthenticationResult.AccountLocked,
                                                            authenticatedUser: null, lockTimeRemainingMinutes: remainingMinutes));
                }

                // Validate the password
                Credential matched;
                if (!ValidatePasswordCredential(user.Credentials, password, out matched))
                {
                    _trace.Information($"Password validation failed: {userNameOrEmail}");

                    await UpdateFailedLoginAttempt(user);

                    await Auditing.SaveAuditRecordAsync(
                        new FailedAuthenticatedOperationAuditRecord(
                            userNameOrEmail, AuditedAuthenticatedOperationAction.FailedLoginInvalidPassword));

                    return(new PasswordAuthenticationResult(PasswordAuthenticationResult.AuthenticationResult.BadCredentials));
                }

                var passwordCredentials = user
                                          .Credentials
                                          .Where(c => CredentialTypes.IsPassword(c.Type))
                                          .ToList();

                if (passwordCredentials.Count > 1 ||
                    !passwordCredentials.Any(c => string.Equals(c.Type, CredentialBuilder.LatestPasswordType, StringComparison.OrdinalIgnoreCase)))
                {
                    await MigrateCredentials(user, passwordCredentials, password);
                }

                // Reset failed login count upon successful login
                await UpdateSuccessfulLoginAttempt(user);

                // Return the result
                _trace.Verbose("Successfully authenticated '" + user.Username + "' with '" + matched.Type + "' credential");
                return(new PasswordAuthenticationResult(PasswordAuthenticationResult.AuthenticationResult.Success, new AuthenticatedUser(user, matched)));
            }
        }
Exemple #14
0
        private async Task <AuthenticatedUser> AuthenticateInternal(Func <Credential, Credential> matchCredential, Credential credential)
        {
            if (credential.Type.StartsWith(CredentialTypes.Password.Prefix, StringComparison.OrdinalIgnoreCase))
            {
                // Password credentials cannot be used this way.
                throw new ArgumentException(Strings.PasswordCredentialsCannotBeUsedHere, nameof(credential));
            }

            using (_trace.Activity("Authenticate Credential: " + credential.Type))
            {
                var matched = matchCredential(credential);

                if (matched == null)
                {
                    _trace.Information("No user matches credential of type: " + credential.Type);

                    await Auditing.SaveAuditRecordAsync(
                        new FailedAuthenticatedOperationAuditRecord(null,
                                                                    AuditedAuthenticatedOperationAction.FailedLoginNoSuchUser,
                                                                    attemptedCredential : credential));

                    return(null);
                }

                if (matched.User is Organization)
                {
                    _trace.Information($"Cannot authenticate organization account '{matched.User.Username}'.");

                    await Auditing.SaveAuditRecordAsync(
                        new FailedAuthenticatedOperationAuditRecord(null,
                                                                    AuditedAuthenticatedOperationAction.FailedLoginUserIsOrganization,
                                                                    attemptedCredential : credential));

                    return(null);
                }

                if (matched.HasExpired)
                {
                    _trace.Verbose("Credential of type '" + matched.Type + "' for user '" + matched.User.Username + "' has expired on " + matched.Expires.Value.ToString("O", CultureInfo.InvariantCulture));

                    return(null);
                }

                if (CredentialTypes.IsApiKey(matched.Type) &&
                    !matched.IsScopedApiKey() &&
                    !matched.HasBeenUsedInLastDays(_config.ExpirationInDaysForApiKeyV1))
                {
                    // API key credential was last used a long, long time ago - expire it
                    await Auditing.SaveAuditRecordAsync(
                        new UserAuditRecord(matched.User, AuditedUserAction.ExpireCredential, matched));

                    matched.Expires = _dateTimeProvider.UtcNow;
                    await Entities.SaveChangesAsync();

                    _trace.Verbose(
                        "Credential of type '" + matched.Type
                        + "' for user '" + matched.User.Username
                        + "' was last used on " + matched.LastUsed.Value.ToString("O", CultureInfo.InvariantCulture)
                        + " and has now expired.");

                    return(null);
                }

                // update last used timestamp
                matched.LastUsed = _dateTimeProvider.UtcNow;
                await Entities.SaveChangesAsync();

                _trace.Verbose("Successfully authenticated '" + matched.User.Username + "' with '" + matched.Type + "' credential");

                return(new AuthenticatedUser(matched.User, matched));
            }
        }
Exemple #15
0
 public RequestData(string credential, CredentialTypes type, T data)
 {
     CredentialID   = credential;
     CredentialType = type;
     Data           = data;
 }
Exemple #16
0
 public void SetCredential(CredentialTypes credentialType,
                           byte[] credential,
                           CredentialFormat format)
 {
     WinBiometric.SetCredential(credentialType, credential, format);
 }
Exemple #17
0
 public void RemoveCredential(BiometricIdentity identity, CredentialTypes credentialType)
 {
     WinBiometric.RemoveCredential(identity, credentialType);
 }