ASP.NET MVC tries to load older version of Owin as

2019-04-23 16:05发布

问题:

As a bit of context, I'm developing an ASP.NET MVC 5 application that uses OAuth-based authentication via Microsoft's OWIN implementation, for Facebook and Google only at this stage. Currently (as of v3.0.0, git-commit 4932c2f), the FacebookAuthenticationOptions and GoogleOAuth2AuthenticationOptions don't provide any property to force Facebook nor Google respectively to reauthenticate users (via appending the appropriate query string parameters) when signing in.

Initially, I set out to override the following classes:

  • FacebookAuthenticationOptions
  • GoogleOAuth2AuthenticationOptions
  • FacebookAuthenticationHandler (specifically AuthenticateCoreAsync())
  • GoogleOAuth2AuthenticationHandler (specifically AuthenticateCoreAsync())

yet discovered that the ~AuthenticationHandler classes are marked as internal.

So I pulled a copy of the source for the Katana project (http://katanaproject.codeplex.com/) and modified the source accordingly.

After compiling, I found that there are several dependencies that needed updating in order to use these updated assemblies (Microsoft.Owin.Security.Facebook and Microsoft.Owin.Security.Google) in the MVC project:

  • Microsoft.Owin
  • Microsoft.Owin.Security
  • Microsoft.Owin.Security.Cookies
  • Microsoft.Owin.Security.OAuth
  • Microsoft.Owin.Host.SystemWeb

This was done by replacing the existing project references to the 3.0.0 versions and updating those in web.config. Good news: the project compiles successfully.

In debugging, I received an exception on startup:

An exception of type 'System.IO.FileLoadException' occurred in [MVC web assembly].dll but was not handled in user code

Additional information: Could not load file or assembly 'Microsoft.Owin.Security, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

The underlying exception indicated that Microsoft.AspNet.Identity.Owin was trying to load v2.1.0 of Microsoft.Owin.Security when calling app.UseExternalSignInCookie() from Startup.ConfigureAuth(IAppBuilder app) in Startup.Auth.cs.

Unfortunately that assembly (and its other dependency, Microsoft.AspNet.Identity.Owin) aren't part of the Project Katana solution, and I can't find any accessible repository for these assemblies online.

Are the Microsoft.AspNet.Identity assemblies open source, like the Katana project? Is there a way to fool those assemblies to use the referenced v3.0.0 assemblies instead of v2.1.0? The /bin folder contains the 3.0.0 versions of the Owin assemblies.

I've upgraded the NuGet packages for Microsoft.AspNet.Identity.Owin, and this is still an issue.

Any ideas on how to resolve this issue?

回答1:

I updated to OWin 3.0.1 and that fixed the problem:

Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution

I searched for the references in the list (under NuGet.org) and installed new references for Microsoft.Owin as well as Microsoft.Owin.Security, Microsoft.Owin.Security.Google, Microsoft.Owin.Security.Facebook etc.

I then checked the version number in my packages.config and Web.Config file and found that this had updated correctly:

Packages.config example:

<package id="Microsoft.Owin.Security.Google" version="3.0.1" TargetFramework="net45" />

Web.Config example:

<assemblyIdentity name="Microsoft.Owin.Security" culture="neutral" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />


回答2:

I've found that while FacebookAuthenticationHandler is marked as internal, its abstract base class AuthenticationHandler<TOptions> is fortunately public. In the end, I took the modified version of FacebookAuthenticationHandler from the Katana project source, renamed it and included it in my own solution, so that it still uses the 2.1 libraries and doesn't cause problems with the other NuGet dependencies.

Likewise for GoogleOAuth2AuthenticationHandler.

So, using the Facebook example, I have the following class definitions in my MVC project:

// Overridden to add additional property 'ForceReauthentication'
public class FacebookOAuth2ExtendedOptions : FacebookAuthenticationOptions
...

// Reimplemented v2.1 source with modified method 'ApplyResponseChallengeAsync'
public class FacebookOAuth2CustomHandler : AuthenticationHandler<FacebookOAuth2ExtendedOptions>
...

// Reimplemented v2.1 source, modified to use 'FacebookOAuth2CustomHandler '
public class FacebookOAuth2CustomMiddleware : AuthenticationMiddleware<FacebookOAuth2ExtendedOptions>
...

Finally in the Startup class (App_Start/Startup.Auth.cs), I register the authentication using my custom middleware classes:

public void ConfigureAuth(IAppBuilder app)
{
    ...

    var fbOptions = new FacebookOAuth2ExtendedOptions()
    {
        AppId = facebookAppKey,
        AppSecret = facebookAppSecret,
        ForceReauthentication = true
    };
    app.Use(typeof(FacebookOAuth2CustomMiddleware), app, fbOptions);

    ...
}

Hope this helps others with similar issues.