Example #1
0
        public async Task <IActionResult> Get(int?id, [FromServices] IApplicationContext applicationContext, [FromServices] IContainerResolve containerResolve)
        {
            if (applicationContext.Principal.Authorization.Operations.Count == 0)
            {
                return(Unauthorized());
            }

            string accessToken = null;

            int index = id.HasValue ? id.Value : 1;

            if (applicationContext.Principal.Identity is ClaimsIdentity claimsIdentity)
            {
                if (null != claimsIdentity.BootstrapContext)
                {
                    accessToken = claimsIdentity.BootstrapContext.ToString();
                }
                else
                {
                    if (containerResolve.TryResolve <IKeyValueSettings>("OpenID", out var settings))
                    {
                        if (containerResolve.TryResolve <ITokenProvider>(settings.Values[TokenKeys.ProviderIdKey], out var tokenProvider))
                        {
                            accessToken = (await tokenProvider.GetTokenAsync(settings, claimsIdentity)).AccessToken;
                        }
                    }
                }
            }

            if (!String.IsNullOrEmpty(accessToken))
            {
                var redirectUrl = Request.Query["redirectUrl"][0];

                var redirectUri = redirectUrl.TrimEnd('/') + "/_content/Arc4u.Standard.OAuth2.Blazor/GetToken.html";

                if (accessToken.Length > index * buffer)
                {
                    containerResolve.TryResolve <IKeyValueSettings>("OAuth", out var settings);
                    var thisController = settings.Values[TokenKeys.RootServiceUrlKey].TrimEnd('/') + $"/blazor/{index + 1}&redirectUrl={redirectUrl}&token={accessToken.Substring((index - 1) * buffer, buffer)}";
                    return(Redirect($"{redirectUri}?url={thisController}"));
                }
                else
                {
                    return(Redirect($"{redirectUri}?token={accessToken.Substring((index - 1) * buffer, accessToken.Length - ((index - 1) * buffer))}"));
                }
            }

            return(BadRequest());
        }
        public ClaimsPrincipalMiddleware(RequestDelegate next, IContainerResolve container, ClaimsPrincipalMiddlewareOption option)
        {
            _next = next ?? throw new ArgumentNullException(nameof(next));

            if (null == container)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (null == option)
            {
                throw new ArgumentNullException(nameof(option));
            }

            var logger = container.Resolve <ILogger <ClaimsPrincipalMiddleware> >();

            if (!container.TryResolve <CacheContext>(out _cacheContext))
            {
                logger.Technical().Information("No cache context is available.").Log();
            }

            _option = option;

            _activitySource = container.Resolve <IActivitySourceFactory>()?.GetArc4u();
        }
Example #3
0
        /// <summary>
        /// Create a JwtHttpHandler. Use services.AddHttpHandler to add one and <see cref="ConfigurePrimaryHttpMessageHandler"/> if you need to
        /// customize the HttpHandler.
        /// </summary>
        /// <param name="resolvingName">The name used to resolve the instance of the <see cref="IKeyValueSettings"/> implementation.</param>
        public JwtHttpHandler(IContainerResolve container, string resolvingName, IPlatformParameters parameters = null)
        {
            _container = container ?? throw new ArgumentNullException(nameof(container));

            _logger = container.Resolve <ILogger <JwtHttpHandler> >();

            if (!container.TryResolve(resolvingName, out _settings))
            {
                _logger.Technical().System($"No settings for {resolvingName} is found.").Log();
            }

            _parameters   = parameters;
            _settingsName = null;

            container.TryResolve <IApplicationContext>(out _applicationContext);
        }
Example #4
0
        // On a frontend usage of the handler the application (user) context is always global => we don't have 2 users logged on the same application!
        // So the Handler is using the IContainerResolve which is not scoped and the IApplicationContext is also not scoped because everything is in fact registered as a Singleton.
        // So there is no issue to create even everything in the constructor.

        /// <summary>
        /// Create a JwtHttpHandler with settings <see cref="IKeyValueSettings"/> resolved based on the name "OAuth" and the <see cref="HttpMessageHandler"/> of type <see cref="HttpClientHandler"/>.
        /// </summary>
        public JwtHttpHandler(IContainerResolve container, IPlatformParameters parameters = null, bool skipValidateAuthenticationType = false)
        {
            _container = container ?? throw new ArgumentNullException(nameof(container));

            _logger = container.Resolve <ILogger <JwtHttpHandler> >();

            if (!container.TryResolve("OAuth", out _settings))
            {
                _logger.Technical().System("No settings for OAuth is found.").Log();
            }

            _parameters   = parameters;
            _settingsName = null;

            container.TryResolve <IApplicationContext>(out _applicationContext);
        }
Example #5
0
        // on the backend, we have to retrieve the user context based on his scoped context when we do a request to another
        // service if this was done in the context of a user (via rest api or gRPC service).
        // When we do a call from a service account, in this case the user is fixed and not scoped => so the creation of the user in this
        // case can be a singleton because we do an impersonation!

        /// <summary>
        /// This is a ctor to use only in a backend scenario => where <see cref="IPlatformParameters"/> it is not used!
        /// No inner handler is defined because this will be done via the AddHttpClient method in a service!
        /// </summary>
        /// <param name="container">The scoped container</param>
        /// <param name="resolvingName">The name used to resolve the settings</param>
        public JwtHttpHandler(IContainerResolve container, ILogger <JwtHttpHandler> logger, string resolvingName)
        {
            _container = container ?? throw new ArgumentNullException(nameof(container));

            _logger = logger;

            if (!container.TryResolve(resolvingName, out _settings))
            {
                _logger.Technical().Debug($"No settings for {resolvingName} is found.").Log();
            }


            container.TryResolve <IApplicationContext>(out _applicationContext);
            _parameters   = _applicationContext;
            _settingsName = null;
        }
Example #6
0
        private IApplicationContext GetCallContext(out object parameters, out IContainerResolve containerResolve)
        {
            containerResolve = GetResolver();

            // first priority to the scope one!
            if (null != _accessor?.HttpContext?.RequestServices)
            {
                var ctx = containerResolve.Resolve <IApplicationContext>();
                parameters = ctx;

                // As this is global for an handler, this can be saved at the level of the class.
                // We do this here only when using an accessor => the IContainerResolve is only available in the context of a call not
                // when the JwtHttpHandler is built.
                if (null == _settings && !String.IsNullOrWhiteSpace(_settingsName))
                {
                    if (!containerResolve.TryResolve(_settingsName, out _settings))
                    {
                        _logger.Technical().Debug($"No settings for {_settingsName} is found.").Log();
                    }
                }

                return(ctx);
            }

            parameters = _parameters;

            return(_applicationContext);
        }
Example #7
0
        private async Task <TokenInfo> GetOpenIdTokenAsync(IKeyValueSettings settings, ClaimsIdentity identity)
        {
            // Check the information.
            var messages = new Messages();

            if (null == settings)
            {
                throw new AppException(new Message(ServiceModel.MessageCategory.Technical,
                                                   MessageType.Error,
                                                   "Settings parameter cannot be null."));
            }

            var settingsProviderName = settings.Values.ContainsKey("OpenIdSettingsReader") ? settings.Values["OpenIdSettingsReader"] : "OpenID";

            if (Container.TryResolve <IKeyValueSettings>(settingsProviderName, out var openIdSettings))
            {
                if (!openIdSettings.Values.ContainsKey(TokenKeys.ProviderIdKey))
                {
                    messages.Add(new Message(ServiceModel.MessageCategory.Technical, MessageType.Error, "No Provider defined in OpenId Settings."));
                }
                else
                {
                    var tokenProviderName = openIdSettings.Values[TokenKeys.ProviderIdKey];

                    if (Container.TryResolve <ITokenProvider>(tokenProviderName, out var openIdTokenProvider))
                    {
                        return(await openIdTokenProvider.GetTokenAsync(openIdSettings, identity));
                    }
                    else
                    {
                        messages.Add(new Message(ServiceModel.MessageCategory.Technical, MessageType.Error, $"Cannot resolve a token provider with name {tokenProviderName}."));
                    }
                }
            }
            else
            {
                messages.Add(new Message(ServiceModel.MessageCategory.Technical, MessageType.Error, $"Cannot resolve the KeyValues settings with name {settingsProviderName}."));
            }


            messages.LogAndThrowIfNecessary(this);
            messages.Clear();

            return(null);
        }
        public IObjectSerialization Serializer(string keyName)
        {
            var handlerDefinition = _definitions.Get(keyName);

            if (null == handlerDefinition.Serializer || !_serviceProvider.TryResolve <IObjectSerialization>(handlerDefinition.Serializer, out var serializerFactory))
            {
                return(_serviceProvider.Resolve <IObjectSerialization>());
            }

            return(serializerFactory);
        }
Example #9
0
        /// <summary>
        /// Create a JwtHttpHandler. Use services.AddHttpHandler to add one and <see cref="ConfigurePrimaryHttpMessageHandler"/> if you need to
        /// customize the HttpHandler.
        /// </summary>
        /// <param name="settings">The settings needed for the <see cref="ITokenProvider"/>.</param>
        /// <param name="handler">The handler, can be a <see cref="DelegatingHandler"/></param>
        public JwtHttpHandler(IContainerResolve container, IKeyValueSettings settings, IPlatformParameters parameters = null)
        {
            _container = container ?? throw new ArgumentNullException(nameof(container));

            _logger = container.Resolve <ILogger <JwtHttpHandler> >();

            _settings = settings ?? throw new ArgumentNullException(nameof(settings));

            _parameters   = parameters;
            _settingsName = null;

            container.TryResolve <IApplicationContext>(out _applicationContext);
        }
Example #10
0
        private IObjectSerialization GetSerializer(PubSubDefinition definition)
        {
            if (null == definition)
            {
                throw new ArgumentNullException(nameof(definition));
            }

            if (null == definition.Serializer || !_serviceProvider.TryResolve <IObjectSerialization>(definition.Serializer, out var serializerFactory))
            {
                return(_serviceProvider.Resolve <IObjectSerialization>());
            }

            return(serializerFactory);
        }
Example #11
0
        private void InitializeFromConfig(IConfiguration configuration)
        {
            lock (_lock)
            {
                if (null == configuration)
                {
                    return;
                }

                var config = new Configuration.Caching();
                configuration.Bind("Caching", config);

                Principal = config.Principal;

                if (null != config.Default && !String.IsNullOrWhiteSpace(config.Default))
                {
                    _cacheConfigName = config.Default;

                    if (null != config.Caches)
                    {
                        // retrieve the caches and start if asked!
                        foreach (var cacheConfig in config.Caches)
                        {
                            if (cacheConfig.IsAutoStart)
                            {
                                if (_dependency.TryResolve <ICache>(cacheConfig.Kind, out var cache))
                                {
                                    cache.Initialize(cacheConfig.Name);

                                    _caches.Add(cacheConfig.Name, cache);

                                    _logger.Technical().From <CacheContext>().System($"Instantiate a new instance of a cache with a kind of {cacheConfig.Kind} and named {cacheConfig.Name}.").Log();
                                }
                                else
                                {
                                    _logger.Technical().From <CacheContext>().Error($"Cannot resolve an ICache instance with the name: {cacheConfig.Kind}.").Log();
                                }
                            }
                            else
                            {
                                _uninitializedCaches.Add(cacheConfig.Name, cacheConfig.Kind);
                                _logger.Technical().From <CacheContext>().System($"Register a cache with a kind of {cacheConfig.Kind} and named {cacheConfig.Name} for later.").Log();
                            }
                        }
                    }
                }
            }
        }
Example #12
0
        public Cache(ILogger logger, IContainerResolve container, string identifier)
        {
            Logger = logger;

            if (!container.TryResolve(out TokenCache))
            {
                Logger.Technical().From <Cache>().Error("No implementation for an ITokenCache exists! Check your dependencies.").Log();
                Logger.Technical().From <Cache>().System($"Token cache is skipped for the user identifier: {identifier}.").Log();
            }

            _identifier = identifier;

            // Attach the events.
            BeforeAccess += BeforeAccessNotification;
            AfterAccess  += AfterAccessNotification;
        }
Example #13
0
        public MessagesScope(IContainerResolve container, ILogger logger, string iocResolveName)
        {
            Logger = logger;
            // Create the unit of work list of messages.
            MessagesToPublish.Create();

            // Search for the instance used to send commands and publish events on start of the
            // scope. So if we have a resolving issue, we know it immediately (and not after the work is done.
            if (!container.TryResolve <IEndpointConfiguration>(iocResolveName, out var endpointConfig))
            {
                logger.Technical().From <MessagesScope>().Warning($"Unable to resolve the IEndpointConfiguration with the name '{iocResolveName}'").Log();
                return;
            }

            if (null == endpointConfig.Instance)
            {
                logger.Technical().From <MessagesScope>().Warning($"Instance is null for the IEndpointConfiguration with the name '{iocResolveName}'").Log();
                return;
            }

            _instance = endpointConfig.Instance;
        }
Example #14
0
        public ClientSecretAuthenticationMiddleware(RequestDelegate next, IContainerResolve container, ClientSecretAuthenticationOption option)
        {
            _next = next ?? throw new ArgumentNullException(nameof(next));

            if (null == container)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (null == option)
            {
                throw new ArgumentNullException(nameof(option));
            }

            _logger = container.Resolve <ILogger <ClientSecretAuthenticationMiddleware> >();
            _option = option;

            if (null == option.Settings)
            {
                _logger.Technical().Warning("No settings have been provided.").Log();
                return;
            }

            if (option.Settings.Values.ContainsKey(TokenKeys.ProviderIdKey))
            {
                _hasProvider = container.TryResolve(option.Settings.Values[TokenKeys.ProviderIdKey], out _provider);
            }

            if (!_hasProvider)
            {
                _logger.Technical().Warning("No ClientSecret provider found. Skip ClientSecret capability.").Log();
                return;
            }

            _hasCertificate = null != option.Certificate &&
                              !String.IsNullOrWhiteSpace(option.Certificate.SecretKey) &&
                              !String.IsNullOrWhiteSpace(option.Certificate.Name);

            // check the certificate exists.
            if (_hasCertificate)
            {
                try
                {
                    var certificateInfo = new CertificateInfo
                    {
                        Name = option.Certificate.Name
                    };

                    if (Enum.TryParse(option.Certificate.FindType, out X509FindType x509FindType))
                    {
                        certificateInfo.FindType = x509FindType;
                    }
                    if (Enum.TryParse(option.Certificate.Location, out StoreLocation storeLocation_))
                    {
                        certificateInfo.Location = storeLocation_;
                    }
                    if (Enum.TryParse(option.Certificate.StoreName, out StoreName storeName_))
                    {
                        certificateInfo.StoreName = storeName_;
                    }

                    _certificate = Certificate.FindCertificate(
                        certificateInfo.Name,
                        certificateInfo.FindType,
                        certificateInfo.Location,
                        certificateInfo.StoreName);

                    _logger.Technical().System($"Authentication with certificate secret activated.").Log();
                }
                catch (KeyNotFoundException)
                {
                    _hasCertificate = false;
                    _logger.Technical().Error($"No certificate found with {option.Certificate.FindType} = {option.Certificate.Name} in location = {option.Certificate.Location}.").Log();
                }
                catch (Exception ex)
                {
                    _logger.Technical().Exception(ex).Log();
                }
            }
            else
            {
                _logger.Technical().System($"No authentication  with certificate secret.").Log();
            }

            _activitySource = container.Resolve <IActivitySourceFactory>()?.GetArc4u();
        }
        public BasicAuthenticationMiddleware(RequestDelegate next, IContainerResolve container, BasicAuthenticationContextOption option)
        {
            _next = next ?? throw new ArgumentNullException(nameof(next));

            if (null == container)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (null == option)
            {
                throw new ArgumentNullException(nameof(option));
            }

            if (null == option.Settings)
            {
                throw new ArgumentNullException("Settings defined in option cannot be null.");
            }

            _logger = container.Resolve <ILogger <BasicAuthenticationMiddleware> >();

            if (!string.IsNullOrEmpty(option.DefaultUpn))
            {
                if (!Regex.IsMatch(option.DefaultUpn, @"^@([a-zA-Z0-9]+\.[a-zA-Z0-9]+)"))
                {
                    _logger.Technical().Warning($"Bad upn format, we expect a @ and one point.").Log();
                    option.DefaultUpn = string.Empty;
                }
                else
                {
                    _logger.Technical().Information($"Default upn: {option.DefaultUpn}.").Log();
                }
            }

            if (option.Settings.Values.ContainsKey(TokenKeys.ProviderIdKey))
            {
                _hasProvider = container.TryResolve(option.Settings.Values[TokenKeys.ProviderIdKey], out _provider);
                if (!_hasProvider)
                {
                    _logger.Technical().Error($"No token provider was found with resolution name equal to: {option.Settings.Values[TokenKeys.ProviderIdKey]}.").Log();
                }
            }
            else
            {
                _logger.Technical().Error($"No token provider resolution name is defined in your settings!").Log();
            }

            if (!_hasProvider)
            {
                _logger.Technical().Error($"Basic Authentication capability is deactivated!").Log();
            }

            if (!container.TryResolve(out _tokenCache))
            {
                _logger.Technical().Error($"No token ache are defined for Basic Authentication.").Log();
            }

            _option    = option;
            _container = container;

            _activitySource = container.Resolve <IActivitySourceFactory>()?.GetArc4u();
        }
Example #16
0
        private void AddBearerTokenCallerMetadata <TRequest, TResponse>(ref ClientInterceptorContext <TRequest, TResponse> context)
            where TRequest : class
            where TResponse : class
        {
            var headers = context.Options.Headers;

            // Call doesn't have a headers collection to add to.
            // Need to create a new context with headers for the call.
            if (headers == null)
            {
                headers = new Metadata();
                var options = context.Options.WithHeaders(headers);
                context = new ClientInterceptorContext <TRequest, TResponse>(context.Method, context.Host, options);
            }

            // if we have already an "Authorization" defined, we can skip the code here.
            if (null != headers.GetValue("authorization"))
            {
                _logger.Technical().System($"Authorization header found. Skip adding a bearer token for AuthenticationType: {_settings.Values[TokenKeys.AuthenticationTypeKey]}.").Log();
                return;
            }

            if (null != _accessor)
            {
                _container = _accessor.HttpContext.RequestServices.GetService <IContainerResolve>();
            }

            // As this is global for an handler, this can be saved at the level of the class.
            // We do this here only when using an accessor => the IContainerResolve is only available in the context of a call not
            // when the JwtHttpHandler is built.
            if (null == _settings && !String.IsNullOrWhiteSpace(_settingsName))
            {
                if (!_container.TryResolve(_settingsName, out _settings))
                {
                    _logger.Technical().Debug($"No settings for {_settingsName} is found.").Log();
                }
            }

            if (_container.TryResolve <IApplicationContext>(out var applicationContext))
            {
                _platformParameter = _platformParameter ?? applicationContext?.Principal?.Identity as ClaimsIdentity;
            }


            if (!_settings.Values.TryGetValue(TokenKeys.AuthenticationTypeKey, out var authenticationType))
            {
                _logger.Technical().System($"No antuentication type for {this.GetType().Name}, Check next Interceptor").Log();
                return;
            }

            var inject = authenticationType.Equals("inject", StringComparison.InvariantCultureIgnoreCase);

            // Skip (BE scenario) if the parameter is an identity and the settings doesn't correspond to the identity's type.
            if (_platformParameter is ClaimsIdentity claimsIdentity
                &&
                !inject
                &&
                !claimsIdentity.AuthenticationType.Equals(_settings.Values[TokenKeys.AuthenticationTypeKey], StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }

            // But in case we inject we need something in the platformParameter!
            if (null == _platformParameter && !inject)
            {
                return;
            }

            try
            {
                ITokenProvider provider  = _container.Resolve <ITokenProvider>(_settings.Values[TokenKeys.ProviderIdKey]);
                var            tokenInfo = provider.GetTokenAsync(_settings, _platformParameter).Result;

                if (tokenInfo.ExpiresOnUtc < DateTime.UtcNow)
                {
                    _logger.Technical().System($"Token is expired! Next Interceptor will be called.").Log();
                    return;
                }

                headers.Add("authorization", $"Bearer {tokenInfo.AccessToken}");
            }
            catch (Exception ex)
            {
                _logger.Technical().Exception(ex).Log();
            }


            // Add culture and activityID if exists!
            if (null != applicationContext?.Principal)
            {
                if (null != applicationContext.Principal?.ActivityID && null == headers.GetValue("activityid"))
                {
                    _logger.Technical().System($"Add the activity id to the request for tracing purpose: {applicationContext.Principal.ActivityID}.").Log();
                    headers.Add("activityid", applicationContext.Principal.ActivityID.ToString());
                }

                var culture = applicationContext.Principal.Profile?.CurrentCulture?.TwoLetterISOLanguageName;
                if (null != culture && null == headers.GetValue("culture"))
                {
                    _logger.Technical().System($"Add the current culture to the request: {applicationContext.Principal.Profile?.CurrentCulture?.TwoLetterISOLanguageName}").Log();
                    headers.Add("culture", culture);
                }
            }
        }