vradarserver / vrs

A .NET web server that can plot the positions of aircraft on a map
http://www.virtualradarserver.co.uk/
Other
267 stars 50 forks source link

CORS issue when working with authentication #116

Open dl2alf opened 6 months ago

dl2alf commented 6 months ago

In a cross domain scenario all browsers do a CORS preflight request to check permissions of the requested web site. VRS basically does handle CORS when CORS support is activated in Tools/Options/Website. But if both CORS support and user authentication is enabled I got an CORS error reported and the browser refuses to work with the data received.

What I could investigate so far: Browsers always send CORS preflight requests without authentication in order to keep the credentials secure. In VRS, the standard pipeline build for websites puts the authentication filter before the CORS handler. As a result, VRS web server answers the preflight request with Error 403 (not authenticated), stops the pipeline and we are done.

I am not very familiar with VRS architecture but a solution might be to skip authentication filter in case of CORS preflight requests. Furthermore, browsers need a "Access-Control-Allow-Credentials" header set to TRUE on CORS GET repsonses to pass the last browser check.

I could manage to compile a working VRS web server from the current source tree by modifying the following two procedures:

  1. in BasicAuthenticationFilter.cs

    _///

    /// Returns true if the request is authenticated, false otherwise. If the request has not been /// authenticated then pipeline processing should be stopped. /// /// /// private bool Authenticated(IDictionary<string, object> environment) { var result = true;

       var sharedConfig = _SharedConfiguration.Get();
       var context = OwinContext.Create(environment);
    
       // skip authentication check in case of CORS preflight request (OPTIONS)
       if (context.RequestHttpMethod != HttpMethod.Options)
       {
           // proceed with basic authentication check
           var isAdminOnlyPath = _AuthenticationConfiguration.IsAdministratorPath(context.RequestPathNormalised);
           var isGlobalAuthenticationEnabled = sharedConfig.WebServerSettings.AuthenticationScheme == AuthenticationSchemes.Basic;
    
           if (isAdminOnlyPath || isGlobalAuthenticationEnabled)
           {
               result = false;
    
               string userName = null;
               string password = null;
               if (ExtractCredentials(context, ref userName, ref password))
               {
                   var cachedUser = _BasicAuthentication.GetCachedUser(userName);
                   var cachedUserTag = _BasicAuthentication.GetCachedUserTag(cachedUser);
                   var isPasswordValid = _BasicAuthentication.IsPasswordValid(cachedUser, cachedUserTag, password);
    
                   result = isPasswordValid && (!isAdminOnlyPath || cachedUser.IsAdministrator);
                   if (result)
                   {
                       context.RequestPrincipal = _BasicAuthentication.CreatePrincipal(cachedUser, cachedUserTag);
                   }
               }
    
               if (!result)
               {
                   SendNeedsAuthenticationResponse(context);
               }
           }
       }
    
       return result;

    }_

  2. In CorsHandler.cs

    __///

    /// Adds Allow-Origin headers to simple requests that match the origin. /// /// /// private void HandleSimpleRequest(OwinContext context, string origin) { if(OriginIsAllowed(origin)) { context.ResponseHeadersDictionary["Access-Control-Allow-Origin"] = origin; }

       // add access control header to pass CORS check of browsers
       var sharedConfig = _SharedConfiguration.Get();
       if (sharedConfig.WebServerSettings.AuthenticationScheme == AuthenticationSchemes.Basic)
       {
    
           context.ResponseHeadersDictionary["Access-Control-Allow-Credentials"] = "true";
       }

    }__

I kindly ask the maintainers to verify this and to push approbiate code changes to the repository. Thank you in advance!