Use OWIN Ws-Federation package to authenticate against ADFS 3.0

后端 未结 3 1520
梦如初夏
梦如初夏 2021-02-02 16:03

I have an MVC intranet site that needs to use AD accounts for authentication.

I setup ADFS 3.0 (Win Server 2012 R2) and followed this to setup the ADFS Relying Party Tr

相关标签:
3条回答
  • 2021-02-02 16:12

    Yeah.. I came across the same issue. Just do the following and it should work:

        app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType );
    
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
           AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
        });
    
    0 讨论(0)
  • 2021-02-02 16:29

    I've been trying to get my head around this for a while now, and with thanks specifically to Lars Kemmann and Tratcher, I believe the accepted way of doing this is as follows:

    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    
    app.UseCookieAuthentication(
        new CookieAuthenticationOptions { }
    );
    
    app.UseWsFederationAuthentication(
        new WsFederationAuthenticationOptions
        {
            Wtrealm = ConfigurationManager.AppSettings["ida:Wtrealm"],
            MetadataAddress = ConfigurationManager.AppSettings["ida:FedMetadataURI"]
        }
    );
    

    It seems counter-intuitive that you're configuring the default authentication type as 'Cookie Authentication' to get WsFederation to work, however these are really just strings used to identify each piece of middleware (this allows you to register the same type of middleware multiple times, for example), they evaluate as follows:

    • CookieAuthenticationDefaults.AuthenticationType = "Cookies"
    • WsFederationAuthenticationDefaults.AuthenticationType = "Federation"

    What's happening here is that we're telling OWIN that the middleware labelled "Cookies" should be used by default to authenticate requests, we then add the CookieAuthentication middleware (by default this is labelled "Cookies" from the CookieAuthenticationDefaults.AuthenticationType value, so we don't have to write any additional code to set it up), finally we add the FederationAuthentication middleware (this is labelled by WsFederationAuthenticationDefaults.AuthenticationType - i.e. "Federation"), my understanding is that the Federation middleware utilises the Cookie middleware to manage its authentication-related cookies.

    All that's left it to do is configure your app to invoke the middleware at a time of your choosing, this can be achieved in a number of ways, some of which are as follows:

    • By returning a HTTP 401 response
    • By using the [Authorize] attribute on an MVC Controller
    • By calling the OWIN Context IAuthenticationManager's Challenge method (passing in the label of your Federation middleware)

    When I asked this question here, Lars answered with a neat example of how to request authentication for all requests, I then bundled it in to the OWIN pipeline as follows:

    app.Use(
        (context, continuation) =>
        {
            if (
                (context.Authentication.User != null) &&
                (context.Authentication.User.Identity != null) &&
                (context.Authentication.User.Identity.IsAuthenticated)
            )
            {
                return continuation();
            }
            else
            {
                context.Authentication.Challenge(WsFederationAuthenticationDefaults.AuthenticationType);
    
                return Task.Delay(0);
            }
        }
    );
    

    Note that in the first example above, I moved the Wtrealm and MetadataAddress values into my config file for ease of maintenance, they are just simple application settings:

    <appSettings>
        <add key="ida:Wtrealm" value="[app-uri]" />
        <add key="ida:FedMetadataURI" value="https://[adfs-server]/federationmetadata/2007-06/federationmetadata.xml" />
    </appSettings>
    

    I hope this helps.

    0 讨论(0)
  • 2021-02-02 16:30

    Actually, you are just missing this line that is usually before the UseCookieAuthentication method call.

    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    

    in your case it would be

    app.UseExternalSignInCookie(WsFederationAuthenticationDefaults.AuthenticationType);
    

    This is what actually gets executed when you call UseExternalSignInCookie(...), externalAuthenticationType is what you pass in as the string parameter.

    app.SetDefaultSignInAsAuthenticationType(externalAuthenticationType);
    CookieAuthenticationOptions options = new CookieAuthenticationOptions();
    options.AuthenticationType = externalAuthenticationType;
    options.AuthenticationMode = AuthenticationMode.Passive;
    options.CookieName = ".AspNet." + externalAuthenticationType;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(5.0);
    app.UseCookieAuthentication(options);
    

    So, if all you are setting is the AuthenticationType, you can safely just call UseExternalSignInCookie as it does it for you.

    0 讨论(0)
提交回复
热议问题