/// <summary>
        /// Adds the Authentication middleware and a middleware for setting the sensenet current user.
        /// </summary>
        /// <param name="app">The Microsoft.AspNetCore.Builder.IApplicationBuilder to add the middleware to.</param>
        /// <param name="configure">Configure sensenet authentication.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        public static IApplicationBuilder UseSenseNetAuthentication(this IApplicationBuilder app, Action <SenseNetAuthenticationOptions> configure)
        {
            var options = new SenseNetAuthenticationOptions();

            configure?.Invoke(options);

            // add the optional cookie reader middleware - default is false
            if (options.AddJwtCookie)
            {
                app.UseSenseNetJwtCookieReader();
            }

            app.UseAuthentication();
            app.UseSenseNetUser(options, null);

            // add the optional cookie writer middleware - default is false
            if (options.AddJwtCookie)
            {
                app.UseSenseNetJwtCookieWriter();
            }

            return(app);
        }
        /// <summary>
        /// Adds a middleware for setting the sensenet current user.
        /// </summary>
        /// <param name="app">The Microsoft.AspNetCore.Builder.IApplicationBuilder to add the middleware to.</param>
        /// <returns>A reference to this instance after the operation has completed.</returns>
        private static IApplicationBuilder UseSenseNetUser(this IApplicationBuilder app, SenseNetAuthenticationOptions options,
                                                           Action <SenseNetAuthenticationOptions> configure)
        {
            configure?.Invoke(options);

            app.Use(async(context, next) =>
            {
                var identity = context?.User?.Identity;
                User user    = null;

                // At this point the user is already authenticated, which means
                // we can trust the information in the identity: we load the
                // user in elevated mode (using system account).
                if (identity?.IsAuthenticated ?? false)
                {
                    // if the caller provided a custom user loader method
                    if (options.FindUserAsync != null)
                    {
                        user = await options.FindUserAsync(context.User);
                    }
                    else
                    {
                        // Check if there is a sub claim. Look for sub by its simple name or
                        // using the longer name defined by the schema below.
                        var sub = context.User.FindFirst(c =>
                                                         IdentityConstants.ClaimIdentifiers.Contains(c.Type) ||
                                                         c.Properties.Any(p =>
                                                                          string.Equals(p.Key,
                                                                                        "http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/ShortTypeName",
                                                                                        StringComparison.InvariantCultureIgnoreCase) &&
                                                                          p.Value == "sub"))?.Value;

                        if (!string.IsNullOrEmpty(sub))
                        {
                            // try to recognize sub as a user id or username
                            user = SystemAccount.Execute(() =>
                                                         int.TryParse(sub, out var subId) ? Node.Load <User>(subId) : User.Load(sub));
                        }
                    }
                }

                User.Current = user ?? User.DefaultUser;

                if (next != null)
                {
                    await next();
                }
            });

            return(app);
        }