Base solution for your next web application
Ends in:
01 DAYS
01 HRS
01 MIN
01 SEC

Activities of "maharatha"

I added these classes in the core project.

Error in Error Log :

<br> TokenAuthController' is waiting for the following dependencies: - Service 'DOCUHOLD.EDRMS.MultiTenancy.Cache.ITenantCacheExtensions' which was not registered.

Castle.MicroKernel.Handlers.HandlerException: Can't create component 'DOCUHOLD.EDRMS.Web.Controllers.TokenAuthController' as it has dependencies to be satisfied.

I know I am missing something somewhere but not sure where and how to register it.

public interface ITenantCacheExtensions 
    {
        TenantCacheItemExtensions Get(int tenantId);

        TenantCacheItemExtensions Get(string tenancyName);

        TenantCacheItemExtensions GetOrNull(string tenancyName);

        TenantCacheItemExtensions GetOrNull(int tenantId);

    }
public class TenantCacheExtensions<TTenant, TUser> : ITenantCacheExtensions, IEventHandler<EntityChangedEventData<TTenant>>
       where TTenant : AbpTenant<TUser>
       where TUser : AbpUserBase
    {
        private readonly ICacheManager _cacheManager;
        private readonly IRepository<TTenant> _tenantRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public TenantCacheExtensions(
            ICacheManager cacheManager,
            IRepository<TTenant> tenantRepository,
            IUnitOfWorkManager unitOfWorkManager)
        {
            _cacheManager = cacheManager;
            _tenantRepository = tenantRepository;
            _unitOfWorkManager = unitOfWorkManager;
        }

        public virtual TenantCacheItemExtensions Get(int tenantId)
        {
            var cacheItem = GetOrNull(tenantId);

            if (cacheItem == null)
            {
                throw new AbpException("There is no tenant with given id: " + tenantId);
            }

            return cacheItem;
        }

        public virtual TenantCacheItemExtensions Get(string tenancyName)
        {
            var cacheItem = GetOrNull(tenancyName);

            if (cacheItem == null)
            {
                throw new AbpException("There is no tenant with given tenancy name: " + tenancyName);
            }

            return cacheItem;
        }

        public virtual TenantCacheItemExtensions GetOrNull(string tenancyName)
        {
            var tenantId = _cacheManager
                .GetTenantByNameCache()
                .Get(
                    tenancyName.ToLowerInvariant(),
                    () => GetTenantOrNull(tenancyName)?.Id
                );

            return tenantId == null ? null : Get(tenantId.Value);
        }

        public TenantCacheItemExtensions GetOrNull(int tenantId)

        {
             return _cacheManager
                .GetTenantCache()
                .Get(
                    tenantId,
                    () =>
                    {
                        var tenant = GetTenantOrNull(tenantId);
                        if (tenant == null)
                        {
                            return null;
                        }

                        return CreateTenantCacheItem(tenant);
                    }
                );
        }

        protected virtual TenantCacheItemExtensions CreateTenantCacheItem(TTenant tenant)
        {
            return new TenantCacheItemExtensions
            {
                Id = tenant.Id,
                Name = tenant.Name,
                TenancyName = tenant.TenancyName,
                EditionId = tenant.EditionId,
                ConnectionString = SimpleStringCipher.Instance.Decrypt(tenant.ConnectionString),
                IsActive = tenant.IsActive,
                EncryptedAesSessionKey = tenant.EncryptedAesSessionKey,
                KeyId = tenant.KeyId

            };
        }

        [UnitOfWork]
        protected virtual TTenant GetTenantOrNull(int tenantId)
        {
            using (_unitOfWorkManager.Current.SetTenantId(null))
            {
                return _tenantRepository.FirstOrDefault(tenantId);
            }
        }

        [UnitOfWork]
        protected virtual TTenant GetTenantOrNull(string tenancyName)
        {
            using (_unitOfWorkManager.Current.SetTenantId(null))
            {
                return _tenantRepository.FirstOrDefault(t => t.TenancyName == tenancyName);
            }
        }

        public void HandleEvent(EntityChangedEventData<TTenant> eventData)
        {
            var existingCacheItem = _cacheManager.GetTenantCache().GetOrDefault(eventData.Entity.Id);

            _cacheManager
                .GetTenantByNameCache()
                .Remove(
                    existingCacheItem != null
                        ? existingCacheItem.TenancyName.ToLowerInvariant()
                        : eventData.Entity.TenancyName.ToLowerInvariant()
                );

            _cacheManager
                .GetTenantCache()
                .Remove(eventData.Entity.Id);
        }


    }
[Serializable]
    public class TenantCacheItemExtensions
    {
        public const string CacheName = "AbpZeroTenantCache";

        public const string ByNameCacheName = "AbpZeroTenantByNameCache";

        public int Id { get; set; }

        public string Name { get; set; }

        public string TenancyName { get; set; }

        public string ConnectionString { get; set; }

        public int? EditionId { get; set; }

        public bool IsActive { get; set; }

        public object CustomData { get; set; }

        public byte[] EncryptedAesSessionKey { get; set; }

        public string KeyId { get; set; }
    }
 public static class TenantCacheManagerExtensions
    {
        public static ITypedCache<int, TenantCacheItemExtensions> GetTenantCache(this ICacheManager cacheManager)
        {
            return cacheManager.GetCache<int, TenantCacheItemExtensions>(TenantCacheItemExtensions.CacheName);
        }

        public static ITypedCache<string, int?> GetTenantByNameCache(this ICacheManager cacheManager)
        {
            return cacheManager.GetCache<string, int?>(Abp.MultiTenancy.TenantCacheItem.ByNameCacheName);
        }
    }

I have added these four classes :

`public interface ITenantCacheExtensions { TenantCacheItemExtensions Get(int tenantId);

TenantCacheItemExtensions Get(string tenancyName);

TenantCacheItemExtensions GetOrNull(string tenancyName);

TenantCacheItemExtensions GetOrNull(int tenantId);

}``

public class TenantCacheExtensions<TTenant, TUser> : ITenantCacheExtensions, IEventHandler<EntityChangedEventData>

where TTenant : Tenant where TUser : AbpUserBase { private readonly ICacheManager _cacheManager; private readonly IRepository _tenantRepository;

private readonly IUnitOfWorkManager _unitOfWorkManager;

    public TenantCacheExtensions(
        ICacheManager cacheManager,
        IRepository&lt;TTenant&gt; tenantRepository,
        IUnitOfWorkManager unitOfWorkManager)
    {
        _cacheManager = cacheManager;
        _tenantRepository = tenantRepository;
        _unitOfWorkManager = unitOfWorkManager;
    }

    public virtual TenantCacheItemExtensions Get(int tenantId)
    {
        var cacheItem = GetOrNull(tenantId);

        if (cacheItem == null)
        {
            throw new AbpException("There is no tenant with given id: " + tenantId);
        }

        return cacheItem;
    }

    public virtual TenantCacheItemExtensions Get(string tenancyName)
    {
        var cacheItem = GetOrNull(tenancyName);

        if (cacheItem == null)
        {
            throw new AbpException("There is no tenant with given tenancy name: " + tenancyName);
        }

        return cacheItem;
    }

    public virtual TenantCacheItemExtensions GetOrNull(string tenancyName)
    {
        var tenantId = _cacheManager
            .GetTenantByNameCache()
            .Get(
                tenancyName.ToLowerInvariant(),
                () => GetTenantOrNull(tenancyName)?.Id
            );

        return tenantId == null ? null : Get(tenantId.Value);
    }

    public TenantCacheItemExtensions GetOrNull(int tenantId)

    {
         return _cacheManager
            .GetTenantCache()
            .Get(
                tenantId,
                () =>
                {
                    var tenant = GetTenantOrNull(tenantId);
                    if (tenant == null)
                    {
                        return null;
                    }

                    return CreateTenantCacheItem(tenant);
                }
            );
    }

    protected virtual TenantCacheItemExtensions CreateTenantCacheItem(TTenant tenant)
    {
        return new TenantCacheItemExtensions
        {
            Id = tenant.Id,
            Name = tenant.Name,
            TenancyName = tenant.TenancyName,
            EditionId = tenant.EditionId,
            ConnectionString = SimpleStringCipher.Instance.Decrypt(tenant.ConnectionString),
            IsActive = tenant.IsActive,
            EncryptedAesSessionKey = tenant.EncryptedAesSessionKey,
            KeyId = tenant.KeyId

        };
    }

    [UnitOfWork]
    protected virtual TTenant GetTenantOrNull(int tenantId)
    {
        using (_unitOfWorkManager.Current.SetTenantId(null))
        {
            return _tenantRepository.FirstOrDefault(tenantId);
        }
    }

    [UnitOfWork]
    protected virtual TTenant GetTenantOrNull(string tenancyName)
    {
        using (_unitOfWorkManager.Current.SetTenantId(null))
        {
            return _tenantRepository.FirstOrDefault(t => t.TenancyName == tenancyName);
        }
    }

    public void HandleEvent(EntityChangedEventData&lt;TTenant&gt; eventData)
    {
        var existingCacheItem = _cacheManager.GetTenantCache().GetOrDefault(eventData.Entity.Id);

        _cacheManager
            .GetTenantByNameCache()
            .Remove(
                existingCacheItem != null
                    ? existingCacheItem.TenancyName.ToLowerInvariant()
                    : eventData.Entity.TenancyName.ToLowerInvariant()
            );

        _cacheManager
            .GetTenantCache()
            .Remove(eventData.Entity.Id);
    }


}`

`
    public object CustomData { get; set; }

    public byte[] EncryptedAesSessionKey { get; set; }

    public string KeyId { get; set; }
}`

`public static class TenantCacheManagerExtensions
{
    public static ITypedCache&lt;int, TenantCacheItemExtensions&gt; GetTenantCache(this ICacheManager cacheManager)
    {
        return cacheManager.GetCache&lt;int, TenantCacheItemExtensions&gt;(TenantCacheItemExtensions.CacheName);
    }

    public static ITypedCache&lt;string, int?&gt; GetTenantByNameCache(this ICacheManager cacheManager)
    {
        return cacheManager.GetCache&lt;string, int?&gt;(Abp.MultiTenancy.TenantCacheItem.ByNameCacheName);
    }
}`

Then I made changes to ITenanctCache in TokenAuthController

`public class TokenAuthController : EDRMSControllerBase { private const string UserIdentifierClaimType = "http://aspnetzero.com/claims/useridentifier";

    private readonly LogInManager _logInManager;
    private readonly ITenantCacheExtensions _tenantCache;`

When I do this I get Internal Server error, when I change it to ITenantCache it works fine.

Am i missing something ?

Why are you using unique_name claim when it is not a OpenID standard claim :

https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims

Thank You.

No problem, thank you for the response.

Do you mind sharing the code changes you did in the angular side ?

Ok I figured out partially :

` public class OpenIdConnectAuthProviderApi : ExternalAuthProviderApiBase { private readonly IIocResolver _iocResolver; private readonly IExternalAuthConfiguration _externalAuthConfiguration;

    public OpenIdConnectAuthProviderApi(IIocResolver iocResolver, IExternalAuthConfiguration externalAuthConfiguration)
    {
        _iocResolver = iocResolver;
        _externalAuthConfiguration = externalAuthConfiguration;
    }

    public const string Name = "OpenIdConnect";

    public  async Task<ExternalAuthUserInfo> GetUserInfo( string provider, string token )
    {
        ExternalLoginProviderInfo providerInfo = _externalAuthConfiguration.Providers.FirstOrDefault<ExternalLoginProviderInfo>((Func<ExternalLoginProviderInfo, bool>)(p => p.Name == provider));
        var issuer = providerInfo.AdditionalParams["Authority"];
        if (string.IsNullOrEmpty(issuer))
        {
            throw new ApplicationException("Authentication:OpenId:Issuer configuration is required.");
        }

        var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
            issuer + "/.well-known/openid-configuration",
            new OpenIdConnectConfigurationRetriever(),
            new HttpDocumentRetriever());

        var validatedToken = await ValidateToken(token, issuer, configurationManager,providerInfo);

        var fullName = validatedToken.Claims.First(c => c.Type == "fullname").Value;
        var email = validatedToken.Claims.First(c => c.Type == "unique_name").Value;
        var fullNameParts = fullName.Split('.');

        return new ExternalAuthUserInfo
        {
            Provider = Name,
            ProviderKey = validatedToken.Subject,
            Name = fullNameParts[0],
            Surname = fullNameParts[1],
            EmailAddress = email
        };
    }

    private async Task<JwtSecurityToken> ValidateToken(
        string token,
        string issuer,
        IConfigurationManager<OpenIdConnectConfiguration> configurationManager,
        ExternalLoginProviderInfo providerInfo,
        CancellationToken ct = default(CancellationToken))
    {
        if (string.IsNullOrEmpty(token))
        {
            throw new ArgumentNullException(nameof(token));
        }

        if (string.IsNullOrEmpty(issuer))
        {
            throw new ArgumentNullException(nameof(issuer));
        }

        var discoveryDocument = await configurationManager.GetConfigurationAsync(ct);
        var signingKeys = discoveryDocument.SigningKeys;

        var validationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = issuer,
            ValidateIssuerSigningKey = true,
            IssuerSigningKeys = signingKeys,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.FromMinutes(5),
            ValidateAudience = false
        };

        var principal = new JwtSecurityTokenHandler().ValidateToken(token, validationParameters, out var rawValidatedToken);
        //Validate clientId
        if (providerInfo.ClientId != principal.Claims.First(c => c.Type == "aud").Value)
        {
            throw new ApplicationException("ClientId couldn't verified.");
        }

        return (JwtSecurityToken)rawValidatedToken;
    }

    

    public IDisposableDependencyObjectWrapper<IExternalAuthProviderApi> CreateProviderApi(string provider)
    {
        ExternalLoginProviderInfo providerInfo = _externalAuthConfiguration.Providers.FirstOrDefault<ExternalLoginProviderInfo>((Func<ExternalLoginProviderInfo, bool>)(p => p.Name == provider));
        if (providerInfo == null)
            throw new Exception("Unknown external auth provider: " + provider);
        IDisposableDependencyObjectWrapper<IExternalAuthProviderApi> dependencyObjectWrapper = IocResolverExtensions.ResolveAsDisposable<IExternalAuthProviderApi>(this._iocResolver, providerInfo.ProviderApiType);
        dependencyObjectWrapper.Object.Initialize(providerInfo);
        return dependencyObjectWrapper;
    }

    public override Task<ExternalAuthUserInfo> GetUserInfo(string accessCode)
    {
        throw new NotImplementedException();
    }
}

`

I had to add CreateProviderAPi else it was appearing Null with the code you provided.

Then the name token is not being passed as part of id token, which is why I have contacted Okta to get more details, but I guess we have to add the unique_name as one of the custom claims. SO when i changed the claim from name to fullName and added the custom claim it worked fine. Can you please review the code above and see if i am doing right.

I will update what Okta says about the name claim

Above the token preview which Okta is passing. I have added the name and unique_name claims.

Still I am getting the same error.

regarding the above code, can you provide more details on how to implement it. I have the same question regarding the GetuserInfo as asked by the previous user, how am I going to instatiate the providerinfo.

If this doesn't work I will send you my project.

@cmthomps I am currently trying to add custom claims to make the existing code work but I am struggling to get it right. If in the meantime you are able to use the custom code provided then let me know if it works.

Showing 81 to 90 of 206 entries