IdentityServer4 from .net framework 4.6

11,371

Solution 1

For anyone struggling with this and unable to find clear guidance, the answer is to not use UseOpenIdConnectAuthentication at all. Use WSFederationAuthentication in you .net framework mvc app...

Startup.cs :-

using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.WsFederation;
using Owin;

[assembly: OwinStartup(typeof(MvcOwinWsFederation.Startup))]

namespace MvcOwinWsFederation
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });

            app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
            {
                MetadataAddress = "http://localhost:5000/wsfederation",
                Wtrealm = "urn:owinrp",

                SignInAsAuthenticationType = "Cookies"
            });
        }
    }
}

Set up a client for testing in IdentityServer4 as

public static IEnumerable<Client> GetClients()
        {
            return new[]
            {
                new Client
                {
                    ClientId = "urn:owinrp",
                    ProtocolType = ProtocolTypes.WsFederation,

                    RedirectUris = { "http://localhost:10313/" },
                    FrontChannelLogoutUri = "http://localhost:10313/home/signoutcleanup",
                    IdentityTokenLifetime = 36000,

                    AllowedScopes = { "openid", "profile" }
                }
            }
         }

Make sure identity server 4 has this enabled in its statup.cs...

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();

            var cert = new X509Certificate2(Path.Combine(Directory.GetCurrentDirectory(), "idsrvtest.pfx"), "idsrv3test");

            services.AddIdentityServer()
                .AddSigningCredential(cert)
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddTestUsers(TestUsers.Users)
                **.AddWsFederation();**
...
}

Should all work. Found this here...

https://leastprivilege.com/2017/03/03/extending-identityserver4-with-ws-federation-support/

Andy.

Solution 2

Use following setup to integrated identity server 4 open Id connect with asp.net MVC .Net Framework cookie base authentication.

Make sure you have install following nuget

Microsoft.Owin.Security

Microsoft.Owin.Security.Cookies

Microsoft.Owin.Security.OpenIdConnect

Note: update the port number with your application localhost port

public void Configuration(IAppBuilder app)
            {
   app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions {});

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            AuthenticationType = "oidc",
            SignInAsAuthenticationType = "Cookies",
            Authority = "http://localhost:5000/",
            RedirectUri = "http://localhost:44301/signin-oidc",
            PostLogoutRedirectUri = "http://localhost:44301/signout-callback-oidc",
            ClientId = "CP",
            ResponseType = "id_token",
            Scope = "openid profile",
            UseTokenLifetime = false,
            RequireHttpsMetadata = false,
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = (context) =>
                {
                    var identity = context.AuthenticationTicket.Identity;
                    var name = identity.Claims.FirstOrDefault(c => c.Type == identity.NameClaimType)?.Value;

                    return Task.FromResult(0);
                }
            }
        });
    }

Solution 3

I have used .NET framework 4.6.1 for creating Web API, For Identity Provider, I am using Identity Server 4 (Earlier I used Identity Server 3). Initially I did face a problem, but I came up with this workaround which worked perfectly to me. Note that I am using ClientCredentials grantflow.

I am using the same IdentityServer3.AccessTokenValidation library for token validation. The trick is to target to Introspection end point. Below is my configuration which worked.

Here is the configuration for Web API, Note that setting setting ValidationMode property is critical here.

app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
        {
            Authority = ConfigurationManager.AppSettings["AuthServerURI"],
            RequiredScopes = new[] { "comp-read", "stats-read" },
            ClientId = "apiname",
            ClientSecret = "apisecret",
            ValidationMode = ValidationMode.ValidationEndpoint,
            EnableValidationResultCache = true
        });

This is how the APIResource and Client is configured in my IDP.

new ApiResource
            {
                Name = "apiname",
                DisplayName = "Web API",
                Description = "Access to Web API Services",
                ApiSecrets = new List<Secret> {new Secret("apisecret".Sha256())},
                Scopes = new List<Scope> {
                    new Scope("comp-read", "Read access to Comp Db API"),
                    new Scope("stats-read", "Read access to Stats API")
                }

This is how one of the client is configured.

new Client
            {
                ClientName = "name of the client",
                ClientId = "clientname",
                Enabled = true,
                AllowedGrantTypes = GrantTypes.ClientCredentials,
                ClientSecrets = new List<Secret> {
                    new Secret("secretforclient".Sha256())
                },
                AllowedScopes = new List<string>
                {
                    "stats-read"
                },
                AccessTokenLifetime = 1000
            }

Hopefully this helps. Thanks.

Share:
11,371
Andy Walker
Author by

Andy Walker

Updated on June 09, 2022

Comments

  • Andy Walker
    Andy Walker almost 2 years

    My question is about Identity Server 4 and making calls to it from a pre-existing .net framework MVC application.

    I've been through the ID4 "quick starts" as far as getting it run-able and responding correctly to the example .net core MVC application.

    As a quick test I created an basic .Net Framework MVC app and created a startup .cs file...

    using Microsoft.Owin;
    using Microsoft.Owin.Security.Cookies;
    using Microsoft.Owin.Security.OpenIdConnect;
    using Owin;
    using System.Collections.Generic;
    using System.IdentityModel.Tokens;
    
    [assembly: OwinStartup(typeof(MVC_OWIN_Client.Startup))]
    
    namespace MVC_OWIN_Client
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                string baseClientAddress = "http://localhost:44301/";
    
                var authority = JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
    
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = "Cookies"
                });
    
                app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
                {
                    ClientId = "mvc.standard",
                    Authority = "http://localhost:5000/",
                    RedirectUri = baseClientAddress + "signin-oidc",
                    PostLogoutRedirectUri = baseClientAddress + "signout-callback-oidc",
                    ResponseType = "code id_token",
                    Scope = "openid api1 offline_access",
    
                    UseTokenLifetime = false,
                    SignInAsAuthenticationType = "Cookies"
                });
            }
        }
    }
    

    In ID4 config, I created a client to match...

     public static IEnumerable<Client> GetClients()
     {
    
        ...
    
        new Client
            {
            ClientId = "mvc.standard",
                ClientName = "MVC Client2",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
    
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
    
                RedirectUris           = { "http://localhost:44301/signin-oidc" },
                PostLogoutRedirectUris = { "http://localhost:44301/signout-callback-oidc" },
    
                AllowedScopes =
                {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        "api1"
                },
                AllowOfflineAccess = true
        }
    };
    

    The application will progress through the login and permissions page and ID4 finally indicates the user signed in....

    info: IdentityServer4.ResponseHandling.AuthorizeInteractionResponseGenerator[0]
          User consented to scopes: openid, api1, offline_access
    info: IdentityServer4.Endpoints.AuthorizeCallbackEndpoint[0]
          Authorize endpoint response
          {
            "SubjectId": "2",
            "ClientId": "mvc.standard",
            "RedirectUri": "http://localhost:44301/signin-oidc",
            "State": "OpenIdConnect.AuthenticationProperties=pnxKmthLCWSNS1Tj8sBS1K4K-Erxq8_W3Sfj1gg3zXhTCqP-gKV-Hsfgh_pRLPYQcIdVJONhzA3VMdBNv4xqE7y8uX-pzEmeNKBYb0cPAh6Q9lm5knIS5ds9gccYKubK1U0NpnGAW7tw38brRzD7dEG-EkSgXqjnEGeS4pMCrFaG2CFwq08_-KyA85VufscpT3y9sL0hTLLYYbRiJhWIZBOM427piwaHpR-jbl7KXGo",
            "Scope": "openid api1 offline_access"
          }
    info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[10]
          AuthenticationScheme: idsrv signed in.
    info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
          Request finished in 152.1613ms 200 text/html; charset=UTF-8
    

    That's it. The MVC Application is never restored, it sits there until it times-out.

    Has anyone any experience with Identity Server and able to tell me if there is something missing from this? Thanks for your time in advance, Andy.

  • Ashish Patel
    Ashish Patel over 5 years
    Open Id connect is protocol, it is supported by all server side technologies, you may get it out of box in some the technologies like asp.net core provide or we need to implement the same. if there is no out of box solution available in asp.net .net framework then we need to implement it.
  • Andy Walker
    Andy Walker about 5 years
    Your 'solution' doesn't work, yet you vote down a solution that does because it uses ws-federation and was taken from an example by one of the writers of identity server.
  • Ashish Patel
    Ashish Patel about 5 years
    Mention solution is working properly into my application, I think you miss some thing, please share our code for investigate further.
  • user2173353
    user2173353 almost 4 years
    What do you use as an authorization attribute? I want to enforce policies on controllers and I can't figure out how to do this... :(
  • nivs1978
    nivs1978 almost 4 years
    Using IdentityServer4, you cannot use the IdentityServer3.AccessTokenValidation any more, it compiles fine, but won't load beacause of some internal problem with version/references. So how to do this without the reference to the IdentityServer3.AccessTokenValidation NuGet?
  • Vinay Kumar
    Vinay Kumar almost 4 years
    I am using it. it works like a Gem. My API is written using .NET Framework 4.6.1. In this project I am using IdentityServer3.AccessTokenValidation to validate a token generated from IdentityServer4's Introspection end point.
  • nivs1978
    nivs1978 almost 4 years
    I have been unable to find any working samples. I have a web UI (MVC) and the controllers are calling another API (rest/json). I need to protect the web UI with Identity Server 4 and parse the token from the controllers in the Web UI to the rest/json API. All in. NET 4.x. But I cannot find anywhere with working samples or get it to work. I struggled for days now. But if you got it to work with Identity Server 3 NuGet package, I will give it another go.
  • Ashish Patel
    Ashish Patel almost 4 years
    Hi you can use following event and generate authenticate cookie or session to manage the user policy at application level SecurityTokenValidated = (context) => { var identity = context.AuthenticationTicket.Identity; var name = identity.Claims.FirstOrDefault(c => c.Type == identity.NameClaimType)?.Value; //TODO: generate auth ticket or cookies or session return Task.FromResult(0); }
  • DevSay
    DevSay over 3 years
    @Vinay I tried your solution but I still get Unauthorized error
  • Prany
    Prany almost 2 years
    @nivs1978 did you manage to solve this or any working example if u remember
  • nivs1978
    nivs1978 almost 2 years
    @Prany Yes, I will try to find the sample on Monday. However I found that WinForm can be compiled in .Net 6, so that makes things more easy. However I will find a working .Net 4.6 sample,for you.