IdentityServer4 from .net framework 4.6
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.
Andy Walker
Updated on June 09, 2022Comments
-
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 over 5 yearsOpen 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 about 5 yearsYour '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 about 5 yearsMention solution is working properly into my application, I think you miss some thing, please share our code for investigate further.
-
user2173353 almost 4 yearsWhat 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 almost 4 yearsUsing 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 almost 4 yearsI 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 almost 4 yearsI 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 almost 4 yearsHi 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 over 3 years@Vinay I tried your solution but I still get Unauthorized error
-
Prany almost 2 years@nivs1978 did you manage to solve this or any working example if u remember
-
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.