Esempio n. 1
0
        protected async Task <ActionResult <List <Api.OAuthClientSecretResponse> > > Get(string partyName)
        {
            try
            {
                if (!ModelState.TryValidateRequiredParameter(partyName, nameof(partyName)))
                {
                    return(BadRequest(ModelState));
                }
                partyName = partyName?.ToLower();

                var oauthDownParty = await tenantRepository.GetAsync <TParty>(await DownParty.IdFormatAsync(RouteBinding, partyName));

                if (oauthDownParty?.Client?.Secrets?.Count > 0)
                {
                    return(Ok(mapper.Map <List <Api.OAuthClientSecretResponse> >(oauthDownParty.Client.Secrets).Set(s => s.ForEach(es => es.Name = new[] { partyName, es.Name }.ToDotList()))));
                }
                else
                {
                    return(Ok(new List <Api.OAuthClientSecretResponse>()));
                }
            }
            catch (CosmosDataException ex)
            {
                if (ex.StatusCode == HttpStatusCode.NotFound)
                {
                    logger.Warning(ex, $"NotFound, Get '{typeof(TParty).Name}' client secrets by name '{partyName}'.");
                    return(NotFound(typeof(TParty).Name, partyName));
                }
                throw;
            }
        }
Esempio n. 2
0
        protected async Task <IActionResult> Delete(string name)
        {
            try
            {
                if (!ModelState.TryValidateRequiredParameter(name, nameof(name)))
                {
                    return(BadRequest(ModelState));
                }
                name = name?.ToLower();

                var partyName      = name.GetFirstInDotList();
                var secretId       = name.GetLastInDotList();
                var oauthDownParty = await tenantRepository.GetAsync <TParty>(await DownParty.IdFormatAsync(RouteBinding, partyName));

                var secret = oauthDownParty.Client.Secrets.Where(s => s.Id == secretId).FirstOrDefault();
                if (secret == null)
                {
                    return(NotFound("Secret", secretId));
                }
                oauthDownParty.Client.Secrets.Remove(secret);
                await tenantRepository.UpdateAsync(oauthDownParty);

                return(NoContent());
            }
            catch (CosmosDataException ex)
            {
                if (ex.StatusCode == HttpStatusCode.NotFound)
                {
                    logger.Warning(ex, $"NotFound, Delete secret from client '{typeof(TParty).Name}' by name '{name}'.");
                    return(NotFound(typeof(TParty).Name, name));
                }
                throw;
            }
        }
Esempio n. 3
0
        private void DownPartyMapping()
        {
            CreateMap <OAuthDownParty, Api.OAuthDownParty>()
            .ForMember(d => d.AllowUpPartyNames, opt => opt.MapFrom(s => s.AllowUpParties.Select(aup => aup.Name)))
            .ReverseMap()
            .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower()))
            .ForMember(d => d.Id, opt => opt.MapFrom(s => DownParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult()))
            .ForMember(d => d.ClaimTransforms, opt => opt.MapFrom(s => OrderClaimTransforms(s.ClaimTransforms)))
            .ForMember(d => d.AllowUpParties, opt => opt.MapFrom(s => s.AllowUpPartyNames.Select(n => new UpPartyLink {
                Name = n.ToLower()
            })));
            CreateMap <OAuthDownClaim, Api.OAuthDownClaim>()
            .ReverseMap();
            CreateMap <OAuthDownClient, Api.OAuthDownClient>()
            .ForMember(d => d.ResourceScopes, opt => opt.MapFrom(s => s.ResourceScopes.OrderBy(rs => rs.Resource)))
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => sc.Scope)))
            .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c.Claim)))
            .ReverseMap();
            CreateMap <OAuthDownResource, Api.OAuthDownResource>()
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => sc)))
            .ReverseMap();
            CreateMap <OAuthDownResourceScope, Api.OAuthDownResourceScope>()
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => s.Scopes)))
            .ReverseMap()
            .ForMember(d => d.Resource, opt => opt.MapFrom(s => s.Resource.ToLower()));
            CreateMap <OAuthDownScope, Api.OAuthDownScope>()
            .ForMember(d => d.VoluntaryClaims, opt => opt.MapFrom(s => s.VoluntaryClaims.OrderBy(vc => vc.Claim)))
            .ReverseMap();

            CreateMap <OidcDownParty, Api.OidcDownParty>()
            .ForMember(d => d.AllowUpPartyNames, opt => opt.MapFrom(s => s.AllowUpParties.Select(aup => aup.Name)))
            .ReverseMap()
            .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower()))
            .ForMember(d => d.Id, opt => opt.MapFrom(s => DownParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult()))
            .ForMember(d => d.ClaimTransforms, opt => opt.MapFrom(s => OrderClaimTransforms(s.ClaimTransforms)))
            .ForMember(d => d.AllowUpParties, opt => opt.MapFrom(s => s.AllowUpPartyNames.Select(n => new UpPartyLink {
                Name = n.ToLower()
            })));
            CreateMap <OidcDownClaim, Api.OidcDownClaim>()
            .ReverseMap();
            CreateMap <OidcDownClient, Api.OidcDownClient>()
            .ForMember(d => d.ResourceScopes, opt => opt.MapFrom(s => s.ResourceScopes.OrderBy(rs => rs.Resource)))
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => sc.Scope)))
            .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c.Claim)))
            .ReverseMap();
            CreateMap <OidcDownScope, Api.OidcDownScope>()
            .ForMember(d => d.VoluntaryClaims, opt => opt.MapFrom(s => s.VoluntaryClaims.OrderBy(vc => vc.Claim)))
            .ReverseMap();

            CreateMap <SamlDownParty, Api.SamlDownParty>()
            .ForMember(d => d.AllowUpPartyNames, opt => opt.MapFrom(s => s.AllowUpParties.Select(aup => aup.Name)))
            .ReverseMap()
            .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower()))
            .ForMember(d => d.Id, opt => opt.MapFrom(s => DownParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult()))
            .ForMember(d => d.ClaimTransforms, opt => opt.MapFrom(s => OrderClaimTransforms(s.ClaimTransforms)))
            .ForMember(d => d.AllowUpParties, opt => opt.MapFrom(s => s.AllowUpPartyNames.Select(n => new UpPartyLink {
                Name = n.ToLower()
            })));
        }
Esempio n. 4
0
        public async Task <DownParty> GetDownPartyByNameAsync(Party.IdKey idKey, bool required = true)
        {
            if (idKey == null)
            {
                new ArgumentNullException(nameof(idKey));
            }

            return(await ReadItemAsync <DownParty>(await DownParty.IdFormatAsync(idKey), DataDocument.PartitionIdFormat(idKey), required));
        }
Esempio n. 5
0
 private Task <string> GetId(string name)
 {
     if (EqualsBaseType(0, typeof(MParty), (typeof(UpParty))))
     {
         return(UpParty.IdFormatAsync(RouteBinding, name));
     }
     else if (EqualsBaseType(0, typeof(MParty), (typeof(DownParty))))
     {
         return(DownParty.IdFormatAsync(RouteBinding, name));
     }
     else
     {
         throw new NotSupportedException($"{typeof(MParty)} type not supported.");
     }
 }
Esempio n. 6
0
        protected async Task <ActionResult> Post(Api.OAuthClientSecretRequest secretRequest)
        {
            try
            {
                if (!await ModelState.TryValidateObjectAsync(secretRequest))
                {
                    return(BadRequest(ModelState));
                }
                secretRequest.PartyName = secretRequest.PartyName?.ToLower();

                var oauthDownParty = await tenantRepository.GetAsync <TParty>(await DownParty.IdFormatAsync(RouteBinding, secretRequest.PartyName));

                foreach (var s in secretRequest.Secrets)
                {
                    var secret = new OAuthClientSecret();
                    await secretHashLogic.AddSecretHashAsync(secret, s);

                    if (oauthDownParty.Client.Secrets == null)
                    {
                        oauthDownParty.Client.Secrets = new List <OAuthClientSecret>();
                    }
                    oauthDownParty.Client.Secrets.Add(secret);
                }
                secretRequest.Secrets = oauthDownParty.Client.Secrets.Select(s => s.Id).ToList();
                if (!await ModelState.TryValidateObjectAsync(secretRequest))
                {
                    return(BadRequest(ModelState));
                }
                await tenantRepository.UpdateAsync(oauthDownParty);

                return(Created(new Api.OAuthDownParty {
                    Name = secretRequest.PartyName
                }));
            }
            catch (CosmosDataException ex)
            {
                if (ex.StatusCode == HttpStatusCode.Conflict)
                {
                    logger.Warning(ex, $"Conflict, Create secret on client '{typeof(TParty).Name}' by name '{secretRequest.PartyName}'.");
                    return(Conflict(typeof(TParty).Name, secretRequest.PartyName));
                }
                throw;
            }
        }
Esempio n. 7
0
        private async Task <bool> ValidateClientResourceScopesAsync <TClient, TScope, TClaim>(ModelStateDictionary modelState, OAuthDownParty <TClient, TScope, TClaim> oauthDownParty) where TClient : OAuthDownClient <TScope, TClaim> where TScope : OAuthDownScope <TClaim> where TClaim : OAuthDownClaim
        {
            var isValid = true;

            if (oauthDownParty.Client?.ResourceScopes?.Count() > 0)
            {
                try
                {
                    var duplicatedResourceScope = oauthDownParty.Client.ResourceScopes.GroupBy(r => r.Resource).Where(g => g.Count() > 1).FirstOrDefault();
                    if (duplicatedResourceScope != null)
                    {
                        throw new ValidationException($"Duplicated resource scope, resource '{duplicatedResourceScope.Key}'.");
                    }

                    foreach (var resourceScope in oauthDownParty.Client.ResourceScopes.Where(rs => !rs.Resource.Equals(oauthDownParty.Name, System.StringComparison.Ordinal)))
                    {
                        var duplicatedScope = resourceScope.Scopes?.GroupBy(s => s).Where(g => g.Count() > 1).FirstOrDefault();
                        if (duplicatedScope != null)
                        {
                            throw new ValidationException($"Duplicated scope in resource scope, resource '{resourceScope.Resource} scope '{duplicatedScope.Key}'.");
                        }
                        try
                        {
                            // Test if Down-party exists.
                            var resourceDownParty = await tenantService.GetAsync <OAuthDownParty>(await DownParty.IdFormatAsync(RouteBinding, resourceScope.Resource));

                            if (resourceScope.Scopes?.Count > 0)
                            {
                                foreach (var scope in resourceScope.Scopes)
                                {
                                    if (!(resourceDownParty.Resource?.Scopes?.Where(s => s.Equals(scope, System.StringComparison.Ordinal)).Count() > 0))
                                    {
                                        throw new ValidationException($"Resource '{resourceScope.Resource}' scope '{scope}' not found.");
                                    }
                                }
                            }
                        }
                        catch (CosmosDataException ex)
                        {
                            if (ex.StatusCode == HttpStatusCode.NotFound)
                            {
                                isValid = false;
                                var errorMessage = $"Resource scope down-party resource '{resourceScope.Resource}' not found.";
                                logger.Warning(ex, errorMessage);
                                modelState.TryAddModelError($"{nameof(oauthDownParty.Client)}.{nameof(oauthDownParty.Client.ResourceScopes)}".ToCamelCase(), errorMessage);
                            }
                            else
                            {
                                throw;
                            }
                        }
                    }

                    var appResourceScope = oauthDownParty.Client.ResourceScopes.Where(rs => rs.Resource.Equals(oauthDownParty.Name, System.StringComparison.Ordinal)).SingleOrDefault();
                    if (appResourceScope != null && appResourceScope.Scopes?.Count() > 0)
                    {
                        foreach (var scope in appResourceScope.Scopes)
                        {
                            if (!(oauthDownParty.Resource?.Scopes?.Where(s => s.Equals(scope, StringComparison.Ordinal)).Count() > 0))
                            {
                                if (oauthDownParty.Resource == null)
                                {
                                    oauthDownParty.Resource = new OAuthDownResource {
                                        Scopes = new List <string>()
                                    };
                                }
                                oauthDownParty.Resource.Scopes.Add(scope);
                            }
                        }
                    }
                }
                catch (ValidationException vex)
                {
                    isValid = false;
                    logger.Warning(vex);
                    modelState.TryAddModelError($"{nameof(oauthDownParty.Client)}.{nameof(oauthDownParty.Client.ResourceScopes)}.{nameof(OAuthDownResourceScope.Scopes)}".ToCamelCase(), vex.Message);
                }
            }
            return(isValid);
        }
Esempio n. 8
0
        private void DownPartyMapping()
        {
            CreateMap <OAuthDownParty, Api.OAuthDownParty>()
            .ForMember(d => d.AllowUpPartyNames, opt => opt.MapFrom(s => s.AllowUpParties.Select(aup => aup.Name)))
            .ReverseMap()
            .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower()))
            .ForMember(d => d.Id, opt => opt.MapFrom(s => DownParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult()))
            .ForMember(d => d.ClaimTransforms, opt => opt.MapFrom(s => OrderClaimTransforms(s.ClaimTransforms)))
            .ForMember(d => d.AllowUpParties, opt => opt.MapFrom(s => s.AllowUpPartyNames.Select(n => new UpPartyLink {
                Name = n.ToLower()
            })));
            CreateMap <OAuthDownClaim, Api.OAuthDownClaim>()
            .ReverseMap();
            CreateMap <OAuthDownClient, Api.OAuthDownClient>()
            .ReverseMap()
            .ForMember(d => d.ResourceScopes, opt => opt.MapFrom(s => s.ResourceScopes.OrderBy(rs => rs.Resource)))
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => sc.Scope)))
            .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c.Claim)));
            CreateMap <OAuthDownResource, Api.OAuthDownResource>()
            .ReverseMap()
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => sc)));
            CreateMap <OAuthDownResourceScope, Api.OAuthDownResourceScope>()
            .ReverseMap()
            .ForMember(d => d.Resource, opt => opt.MapFrom(s => s.Resource.ToLower()))
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => s.Scopes)));
            CreateMap <OAuthDownScope, Api.OAuthDownScope>()
            .ReverseMap()
            .ForMember(d => d.VoluntaryClaims, opt => opt.MapFrom(s => s.VoluntaryClaims.OrderBy(vc => vc.Claim)));

            CreateMap <OidcDownParty, Api.OidcDownParty>()
            .ForMember(d => d.AllowUpPartyNames, opt => opt.MapFrom(s => s.AllowUpParties.Select(aup => aup.Name)))
            .ReverseMap()
            .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower()))
            .ForMember(d => d.Id, opt => opt.MapFrom(s => DownParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult()))
            .ForMember(d => d.ClaimTransforms, opt => opt.MapFrom(s => OrderClaimTransforms(s.ClaimTransforms)))
            .ForMember(d => d.AllowUpParties, opt => opt.MapFrom(s => s.AllowUpPartyNames.Select(n => new UpPartyLink {
                Name = n.ToLower()
            })));
            CreateMap <OidcDownClaim, Api.OidcDownClaim>()
            .ReverseMap();
            CreateMap <OidcDownClient, Api.OidcDownClient>()
            .ReverseMap()
            .ForMember(d => d.ResourceScopes, opt => opt.MapFrom(s => s.ResourceScopes.OrderBy(rs => rs.Resource)))
            .ForMember(d => d.Scopes, opt => opt.MapFrom(s => s.Scopes.OrderBy(sc => sc.Scope)))
            .ForMember(d => d.Claims, opt => opt.MapFrom(s => s.Claims.OrderBy(c => c.Claim)));
            CreateMap <OidcDownScope, Api.OidcDownScope>()
            .ReverseMap()
            .ForMember(d => d.VoluntaryClaims, opt => opt.MapFrom(s => s.VoluntaryClaims.OrderBy(vc => vc.Claim)));

            CreateMap <SamlDownParty, Api.SamlDownParty>()
            .ForMember(d => d.AllowUpPartyNames, opt => opt.MapFrom(s => s.AllowUpParties.Select(aup => aup.Name)))
            .ForMember(d => d.AuthnRequestBinding, opt => opt.MapFrom(s => s.AuthnBinding.RequestBinding))
            .ForMember(d => d.AuthnResponseBinding, opt => opt.MapFrom(s => s.AuthnBinding.ResponseBinding))
            .ForMember(d => d.LogoutRequestBinding, opt => opt.MapFrom(s => s.LogoutBinding != null ? (Api.SamlBindingTypes?)s.LogoutBinding.RequestBinding: null))
            .ForMember(d => d.LogoutResponseBinding, opt => opt.MapFrom(s => s.LogoutBinding != null ? (Api.SamlBindingTypes?)s.LogoutBinding.ResponseBinding: null))
            .ReverseMap()
            .ForMember(d => d.Name, opt => opt.MapFrom(s => s.Name.ToLower()))
            .ForMember(d => d.Id, opt => opt.MapFrom(s => DownParty.IdFormatAsync(RouteBinding, s.Name.ToLower()).GetAwaiter().GetResult()))
            .ForMember(d => d.ClaimTransforms, opt => opt.MapFrom(s => OrderClaimTransforms(s.ClaimTransforms)))
            .ForMember(d => d.AllowUpParties, opt => opt.MapFrom(s => s.AllowUpPartyNames.Select(n => new UpPartyLink {
                Name = n.ToLower()
            })))
            .ForMember(d => d.AuthnBinding, opt => opt.MapFrom(s => new SamlBinding
            {
                RequestBinding  = s.AuthnRequestBinding.HasValue ? (SamlBindingTypes)s.AuthnRequestBinding.Value : SamlBindingTypes.Post,
                ResponseBinding = s.AuthnResponseBinding.HasValue ? (SamlBindingTypes)s.AuthnResponseBinding.Value : SamlBindingTypes.Post,
            }))
            .ForMember(d => d.LogoutBinding, opt => opt.MapFrom(s => new SamlBinding
            {
                RequestBinding  = s.LogoutRequestBinding.HasValue ? (SamlBindingTypes)s.LogoutRequestBinding.Value : SamlBindingTypes.Post,
                ResponseBinding = s.LogoutResponseBinding.HasValue ? (SamlBindingTypes)s.LogoutResponseBinding.Value : SamlBindingTypes.Post,
            }));
        }