public async Task When_ResourceOwner_Does_Not_Exist_Then_ReturnsNull()
        {
            const string subject = "invalid_subject";

            InitializeFakeObjects();

            var owner = await _resourceOwnerRepository.Get(subject, CancellationToken.None).ConfigureAwait(false);

            Assert.Null(owner);
        }
        public async Task <Option> Execute(string subject, string twoFactorAuth, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(subject))
            {
                _logger.LogError("Subject is null");
                throw new ArgumentNullException(nameof(subject));
            }

            var resourceOwner = await _resourceOwnerRepository.Get(subject, cancellationToken).ConfigureAwait(false);

            if (resourceOwner == null)
            {
                _logger.LogError(Strings.TheRoDoesntExist);
                return(new Option.Error(
                           new ErrorDetails
                {
                    Title = ErrorCodes.InternalError,
                    Detail = Strings.TheRoDoesntExist,
                    Status = HttpStatusCode.InternalServerError
                }));
            }

            resourceOwner.TwoFactorAuthentication = twoFactorAuth;
            return(await _resourceOwnerRepository.Update(resourceOwner, cancellationToken).ConfigureAwait(false));
        }
示例#3
0
        public async Task <IActionResult> Get(string id, CancellationToken cancellationToken)
        {
            var resourceOwner = await _resourceOwnerRepository.Get(id, cancellationToken).ConfigureAwait(false);

            if (resourceOwner == null)
            {
                return(BadRequest(
                           new ErrorDetails
                {
                    Status = HttpStatusCode.BadRequest,
                    Detail = Strings.TheRoDoesntExist,
                    Title = ErrorCodes.InvalidRequest
                }));
            }

            return(Ok(resourceOwner));
        }
示例#4
0
        public async Task <Option <ResourceOwner> > Execute(
            ClaimsPrincipal claimsPrincipal,
            CancellationToken cancellationToken)
        {
            var claimsIdentity = claimsPrincipal.Identity as ClaimsIdentity;

            if (claimsIdentity?.IsAuthenticated != true)
            {
                _logger.LogError(Strings.TheUserNeedsToBeAuthenticated);
                return(new Option <ResourceOwner> .Error(
                           new ErrorDetails
                {
                    Title = ErrorCodes.UnhandledExceptionCode,
                    Detail = Strings.TheUserNeedsToBeAuthenticated,
                    Status = HttpStatusCode.InternalServerError
                }));
            }

            var subject = claimsPrincipal.GetSubject();

            if (string.IsNullOrWhiteSpace(subject))
            {
                _logger.LogError(Strings.TheSubjectCannotBeRetrieved);
                return(new Option <ResourceOwner> .Error(
                           new ErrorDetails
                {
                    Title = ErrorCodes.UnhandledExceptionCode,
                    Detail = Strings.TheSubjectCannotBeRetrieved,
                    Status = HttpStatusCode.InternalServerError
                }));
            }

            var ro = await _resourceOwnerRepository.Get(subject, cancellationToken).ConfigureAwait(false);

            if (ro is not null)
            {
                return(new Option <ResourceOwner> .Result(ro));
            }

            _logger.LogError(Strings.TheSubjectCannotBeRetrieved);
            return(new Option <ResourceOwner> .Error(
                       new ErrorDetails
            {
                Title = ErrorCodes.UnhandledExceptionCode,
                Detail = Strings.TheRoDoesntExist,
                Status = HttpStatusCode.InternalServerError
            }));
        }
示例#5
0
        public async Task <Option> Execute(string subject, IEnumerable <Claim> claims, CancellationToken cancellationToken)
        {
            var resourceOwner = await _resourceOwnerRepository.Get(subject, cancellationToken).ConfigureAwait(false);

            if (resourceOwner == null)
            {
                _logger.LogError(Strings.TheRoDoesntExist);
                return(new Option.Error(new ErrorDetails
                {
                    Title = ErrorCodes.InternalError,
                    Detail = Strings.TheRoDoesntExist,
                    Status = HttpStatusCode.InternalServerError
                }));
            }

            var claimsToBeRemoved = resourceOwner.Claims.Where(cl => claims.Any(c => c.Type == cl.Type))
                                    .ToArray();

            resourceOwner.Claims = resourceOwner.Claims.Remove(claimsToBeRemoved);

            resourceOwner.Claims =
                resourceOwner.Claims.Add(claims.Where(x => !string.IsNullOrWhiteSpace(x.Value)).ToArray());

            Claim?updatedClaim;

            if ((updatedClaim = resourceOwner.Claims.FirstOrDefault(
                     c => c.Type == OpenIdClaimTypes.UpdatedAt))
                != null)
            {
                resourceOwner.Claims.Remove(updatedClaim);
            }

            resourceOwner.Claims = resourceOwner.Claims.Add(
                new Claim(OpenIdClaimTypes.UpdatedAt, DateTimeOffset.UtcNow.ConvertToUnixTimestamp().ToString()));
            return(await _resourceOwnerRepository.Update(resourceOwner, cancellationToken).ConfigureAwait(false));
        }
示例#6
0
        public async Task <(bool success, string?subject)> Execute(
            ResourceOwner resourceOwner, CancellationToken cancellationToken)
        {
            if (!resourceOwner.IsLocalAccount || string.IsNullOrWhiteSpace(resourceOwner.Subject))
            {
                var subject = await _subjectBuilder.BuildSubject(resourceOwner.Claims, cancellationToken)
                              .ConfigureAwait(false);

                resourceOwner.Subject = subject;
            }

            // 1. Check if the resource owner already exists.
            if (await _resourceOwnerRepository.Get(resourceOwner.Subject, cancellationToken).ConfigureAwait(false) !=
                null)
            {
                return(false, null);
            }

            var additionalClaims = _settings.ClaimsIncludedInUserCreation
                                   .Except(resourceOwner.Claims.Select(x => x.Type))
                                   .Select(x => new Claim(x, string.Empty));

            resourceOwner.Claims = resourceOwner.Claims.Add(additionalClaims);

            // Customize new resource owner.
            _settings.OnResourceOwnerCreated(resourceOwner);

            var now = DateTimeOffset.UtcNow;

            if (_accountFilters != null)
            {
                var isFilterValid = true;
                foreach (var resourceOwnerFilter in _accountFilters)
                {
                    var userFilterResult = await resourceOwnerFilter.Check(resourceOwner.Claims, cancellationToken)
                                           .ConfigureAwait(false);

                    if (userFilterResult.IsValid)
                    {
                        continue;
                    }

                    isFilterValid = false;
                    foreach (var ruleResult in userFilterResult.AccountFilterRules.Where(x => !x.IsValid))
                    {
                        await _eventPublisher.Publish(
                            new FilterValidationFailure(
                                Id.Create(),
                                string.Format(Strings.TheFilterRuleFailed, ruleResult.RuleName),
                                now))
                        .ConfigureAwait(false);

                        foreach (var errorMessage in ruleResult.ErrorMessages)
                        {
                            await _eventPublisher
                            .Publish(new FilterValidationFailure(Id.Create(), errorMessage, now))
                            .ConfigureAwait(false);
                        }
                    }
                }

                if (!isFilterValid)
                {
                    return(false, null);
                }
            }

            resourceOwner.UpdateDateTime = now;
            resourceOwner.CreateDateTime = now;
            if (!await _resourceOwnerRepository.Insert(resourceOwner, cancellationToken).ConfigureAwait(false))
            {
                return(false, null);
            }

            await _eventPublisher.Publish(
                new ResourceOwnerAdded(
                    Id.Create(),
                    resourceOwner.Subject,
                    resourceOwner.Claims.Select(claim => new ClaimData
            {
                Type = claim.Type,
                Value = claim.Value
            })
                    .ToArray(),
                    now))
            .ConfigureAwait(false);

            return(true, resourceOwner.Subject);
        }
示例#7
0
 /// <summary>
 /// Get the profiles linked to the user account.
 /// </summary>
 /// <param name="subject"></param>
 /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the async operation.</param>
 /// <returns></returns>
 private async Task <ResourceOwner?> GetUserProfile(string subject, CancellationToken cancellationToken)
 {
     return(string.IsNullOrWhiteSpace(subject)
         ? null
         : await _resourceOwnerRepository.Get(subject, cancellationToken).ConfigureAwait(false));
 }
        public async Task <Option <string> > Send(string subject, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(subject))
            {
                _logger.LogError(Strings.TheSubjectCannotBeRetrieved);
                return(new Option <string> .Error(
                           new ErrorDetails
                {
                    Title = ErrorCodes.UnhandledExceptionCode,
                    Detail = Strings.TheSubjectCannotBeRetrieved,
                    Status = HttpStatusCode.NotFound
                }));
            }

            var resourceOwner = await _resourceOwnerRepository.Get(subject, cancellationToken).ConfigureAwait(false);

            if (resourceOwner == null)
            {
                _logger.LogError(Strings.TheRoDoesntExist);
                return(new Option <string> .Error(
                           new ErrorDetails
                {
                    Title = ErrorCodes.UnhandledExceptionCode,
                    Detail = Strings.TheRoDoesntExist,
                    Status = HttpStatusCode.NotFound
                }));
            }

            if (string.IsNullOrWhiteSpace(resourceOwner.TwoFactorAuthentication))
            {
                _logger.LogError(Strings.TwoFactorAuthenticationIsNotEnabled);
                return(new Option <string> .Error(
                           new ErrorDetails
                {
                    Title = ErrorCodes.UnhandledExceptionCode,
                    Detail = Strings.TwoFactorAuthenticationIsNotEnabled,
                    Status = HttpStatusCode.NotFound
                }));
            }

            var confirmationCode = new ConfirmationCode
            {
                Value     = await GetCode(subject, cancellationToken).ConfigureAwait(false),
                IssueAt   = DateTimeOffset.UtcNow,
                ExpiresIn = 300
            };

            var service = _twoFactorAuthenticationHandler.Get(resourceOwner.TwoFactorAuthentication) !;

            if (resourceOwner.Claims.All(c => c.Type != service.RequiredClaim))
            {
                throw new ClaimRequiredException(service.RequiredClaim);
            }

            if (!await _confirmationCodeStore.Add(confirmationCode, cancellationToken).ConfigureAwait(false))
            {
                _logger.LogError(Strings.TheConfirmationCodeCannotBeSaved);
                return(new Option <string> .Error(
                           new ErrorDetails
                {
                    Title = ErrorCodes.UnhandledExceptionCode,
                    Detail = Strings.TheConfirmationCodeCannotBeSaved,
                    Status = HttpStatusCode.InternalServerError
                }));
            }

            await _twoFactorAuthenticationHandler.SendCode(confirmationCode.Value, resourceOwner.TwoFactorAuthentication, resourceOwner).ConfigureAwait(false);

            return(new Option <string> .Result(confirmationCode.Value));
        }