.net Core Api authentication with ADFS 2012

不羁的心 提交于 2020-04-11 15:29:13

问题


I need to configure my .Net Core Web Api (.Net Framework) to use ADFS 3.0 (2012) to validate the Bearer tokens sent by our mobile clients.

I am able to generate the access_token from the ADFS server, and I pass it in the Authorization header.

My problem is in the API: how do I configure it to validate and autorize the user?

I searched in many places and I could not find a definitive method of doing it.

What I tried so far:

Used IdentityServer4 (Failed because it uses JWT and ADFS doesn't offer OpenID Tried UseOpenIdConnectAuthentication (found example at IdentityServer4) a custom Middleware I can't use another method, I need to support oAuth2.

So, how do I do it?

Here is my latest try:

    var connectOptions = new OpenIdConnectOptions
    {
        AuthenticationScheme = "adfs",
        SignInScheme = "idsrv.external", //IdentityServerConstants.ExternalCookieAuthenticationScheme,
        SignOutScheme = "idsrv", //IdentityServerConstants.SignoutScheme,
        AutomaticChallenge = false,
        DisplayName = "ADFS",
        Authority = $"https://{options.AdfsHostName}/adfs/oauth2",
        ClientId = options.ClientID,
        ResponseType = "id_token",
        Scope = { "openid profile" },
        CallbackPath = new PathString("/signin-adfs"),
        SignedOutCallbackPath = new PathString("/signout-callback-adfs"),
        RemoteSignOutPath = new PathString("/signout-adfs"),
        ClaimsIssuer = $"https://{options.AdfsHostName}/adfs/services/trust",
        //TokenValidationParameters = new TokenValidationParameters
        //{
        //    ValidateIssuer = true,
        //    ValidIssuer = $"https://{options.AdfsHostName}/adfs/services/trust"
        //},

    };

    app.UseOpenIdConnectAuthentication(connectOptions);

I get a very quick 401 on every calls, with a valid token. In fact, while I see the connection in the console window, I don't see any other log in the Roslyn console window regarding the security validation.

I'm currently using ASP.Net Core 1.1.X, and if I can I'd avoid moving to .Net Core 2.0, as we are late in the project and it contains many breaking changes...

Feel free to ask for more info, and I'll appreciate all the good advices!


回答1:


As it turns out, we can use the JwtBearerAuthentication with ADFS 3.0.

My initial problem with it was that it went to fetch the metadata at /.well-known/openid-configuration, but ADFS 3.0 does not support OpenID and this returns a 404.

I read in another post (I'll update it when I find it) that if with the right configuration, it won't need to fetch the config. But what configuration?

Well I found deep in the (MS) code that if one pass an OpenIdConnectConfiguration object to the Configuration property of the JwtBearerOptions, it wont fetch the metadata.

So here is my code now:

var rawCertData = Convert.FromBase64String(options.X509SigninCertificate);

X509Certificate2 cert = new X509Certificate2(rawCertData);

SecurityKey signingKey = new X509SecurityKey(cert);

The X509 cert data comes from the supported adfs metadata at this url

https://Your.ADFS.Site/FederationMetadata/2007-06/FederationMetadata.xml 

It contains this:

<KeyDescriptor use="signing">
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data>
            <X509Certificate>SOMEUUENCDODEDSTRING=</X509Certificate>
        </X509Data>
    </KeyInfo>
</KeyDescriptor>

I simply copied the UUEncoded string in my settings' X509SigninCertificate property.

var tokenValidationParameters = new TokenValidationParameters
        {
            // The signing key must match!
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = signingKey,

            // Validate the JWT Issuer (iss) claim
            ValidateIssuer = true,
            ValidIssuer = $"https://{options.AdfsHostName}/adfs/services/trust",

            // Validate the JWT Audience (aud) claim
            ValidateAudience = true,
            ValidAudience = options.ClientUri, //"https://YOUR-AUDIENCE/",

            // Validate the token expiry
            ValidateLifetime = true,


            // If you want to allow a certain amount of clock drift, set that here:
            ClockSkew = TimeSpan.Zero
        };

        var connectOptions = new OpenIdConnectConfiguration
        {
            Issuer = $"https://{options.AdfsHostName}/adfs/services/trust",
        };

        app.UseJwtBearerAuthentication(new JwtBearerOptions
        {
            AutomaticAuthenticate = true,
            AutomaticChallenge = true,
            TokenValidationParameters = tokenValidationParameters,
            Configuration = connectOptions                
        });

The important line here is

Configuration = connectOptions

By doing this, you tell the validator to not fetch the metadata. Simple as that.

I was able to validate my token (AUD, ISS and SIGN) and I can use ADFS in my project.




回答2:


Only ADFS 2016 supports OpenID Connect. If you want to use the OAuth endpoint in 2012, you need to write your own authorisation handler. An example to build on would be ASP.NET Core's own Twitter implementation. Note that these handlers need to be implemented differently in ASP.NET Core 1.* vs 2.0+.



来源:https://stackoverflow.com/questions/47565098/net-core-api-authentication-with-adfs-2012

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!