< Summary - CoreWCF Coverage — PR #1766

Information
Class: CoreWCF.Security.LdapAdapter
Assembly: CoreWCF.Primitives
File(s): /home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/LdapAdapter.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 56
Coverable lines: 56
Total lines: 119
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 36
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
RetrieveClaimsAsync()0%36360%

File(s)

/home/runner/work/CoreWCF/CoreWCF/src/CoreWCF.Primitives/src/CoreWCF/Security/LdapAdapter.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.DirectoryServices.Protocols;
 7using System.Linq;
 8using System.Text;
 9using System.Threading.Tasks;
 10using CoreWCF.IdentityModel.Claims;
 11using Microsoft.Extensions.Caching.Memory;
 12
 13namespace CoreWCF.Security
 14{
 15    internal static class LdapAdapter
 16    {
 17        public static async Task<List<Claim>> RetrieveClaimsAsync(LdapSettings settings, string originalUserName)
 18        {
 019            var upnIndex = originalUserName.IndexOf('@');
 020            var userAccountName = "";
 021            if (upnIndex == -1)
 22            {
 023                int domainIndex = originalUserName.IndexOf("\\");
 024                if (domainIndex == -1)
 025                    return null;
 026                userAccountName = originalUserName.Substring(domainIndex + 1);
 27            }
 28            else
 29            {
 030                userAccountName = originalUserName.Substring(0, upnIndex);
 31            }
 32
 033            List<Claim> roleClaims = new List<IdentityModel.Claims.Claim>();
 34
 035            if (settings.ClaimsCache.TryGetValue<IEnumerable<string>>(originalUserName, out var cachedClaims))
 36            {
 037                foreach (var claim in cachedClaims)
 38                {
 039                    roleClaims.Add(new Claim(ClaimTypes.Role, claim, Rights.Identity));
 40                }
 41
 042                return roleClaims;
 43            }
 44
 045            var distinguishedName = settings.Domain.Split('.').Select(name => $"dc={name}").Aggregate((a, b) => $"{a},{b
 046            var retrievedClaims = new List<string>();
 047            if (!string.IsNullOrEmpty(settings.OrgUnit))
 48            {
 049                distinguishedName = "OU=" + settings.OrgUnit + "," + distinguishedName;
 50            }
 51
 052            var genericFilter = $"(&(objectClass=user)(sAMAccountName={userAccountName}))"; // This is using ldap search
 053            var upnFilter = $"(&(objectClass=user)(userPrincipalName={originalUserName}))";
 054            var genericSearchRequest = new SearchRequest(distinguishedName, genericFilter, SearchScope.Subtree, null);
 055            var upnSearchRequest = new SearchRequest(distinguishedName, upnFilter, SearchScope.Subtree, null);
 056            SearchResponse searchResponse = null;
 57            try
 58            {
 059                if (upnIndex > 0)
 60                {
 061                    searchResponse = (SearchResponse)await Task<DirectoryResponse>.Factory.FromAsync(
 062                    settings.LdapConnection.BeginSendRequest, settings.LdapConnection.EndSendRequest,
 063                    upnSearchRequest, PartialResultProcessing.NoPartialResultSupport, null);
 064                    if(searchResponse !=null && searchResponse.Entries != null && searchResponse.Entries.Count > 1)
 65                    {
 066                        throw new Exception(SR.DuplicateUPN); //resource
 67                    }
 68                }
 069                if (searchResponse == null || searchResponse.Entries == null || searchResponse.Entries.Count == 0)
 70                {
 071                    searchResponse = (SearchResponse)await Task<DirectoryResponse>.Factory.FromAsync(
 072                    settings.LdapConnection.BeginSendRequest, settings.LdapConnection.EndSendRequest,
 073                    genericSearchRequest, PartialResultProcessing.NoPartialResultSupport, null);
 74                }
 075            }
 076            catch (Exception ex)
 77            {
 78
 079                if (searchResponse?.ErrorMessage != null)
 80                {
 081                    throw new Exception(searchResponse.ErrorMessage);
 82                }
 83                else
 84                {
 085                    throw ex;
 86                }
 87            }
 88
 089            if (searchResponse.Entries.Count > 0)
 90            {
 091                var userFound = searchResponse.Entries[0]; //Get the object that was found on ldap
 092                var memberof = userFound.Attributes["memberof"]; // You can access ldap Attributes with Attributes prope
 93
 094                foreach (var group in memberof)
 95                {
 96                    // Example distinguished name: CN=TestGroup,DC=KERB,DC=local
 097                    var groupDN = $"{Encoding.UTF8.GetString((byte[])group)}";
 098                    var groupCN = groupDN.Split(',')[0].Substring("CN=".Length);
 099                    retrievedClaims.Add(groupCN);
 100                }
 101
 0102                var entrySize = originalUserName.Length * 2; //Approximate the size of stored key in memory cache.
 0103                foreach (var claim in retrievedClaims)
 104                {
 0105                    roleClaims.Add(new Claim(ClaimTypes.Role, claim, Rights.Identity));
 0106                    entrySize += claim.Length * 2; //Approximate the size of stored value in memory cache.
 107                }
 108
 0109                settings.ClaimsCache.Set(originalUserName,
 0110                    retrievedClaims,
 0111                    new MemoryCacheEntryOptions()
 0112                        .SetSize(entrySize)
 0113                        .SetSlidingExpiration(settings.ClaimsCacheSlidingExpiration)
 0114                        .SetAbsoluteExpiration(settings.ClaimsCacheAbsoluteExpiration));
 115            }
 0116            return roleClaims;
 0117        }
 118    }
 119}

Methods/Properties

RetrieveClaimsAsync()