This scenario involves idsrv3 as both an IDP to an ASP.NET MVC application and as a RP to ADFS. Also I'm using the InMemory option.
So the authentication chain is:
RP --> IS --> ADFS
ADFS is ADFS ("AD FS") 3.0 and IS is version 3. Everything is via WS-Fed. This is being invoked by the Host.Web sample in idsrv3.
Refer to the documentation that has a WS-Federation section at the bottom.
You need two NuGet packages.
Microsoft.Owin.Security.WsFederation
IdentityServer3 - WS-Federation Plugin
Note that the Owin.Security.WsFederation plugin is implemented by Katana. It appears that the plugin only supports consuming metadata. It doesn't appear to support publishing it. This is for upstream federation.
The idsrv3 WS-Federation plugin is implemented by thinktecture. This does generate metadata. This is for downstream federation.
The MVC application is set up as per IdentityServer : Identity Server 3 as a WS-Federation IDP with an ASP.NET MVC application.
You need to change the following:
- IdentityServerExtensions.cs in the Host.Configuration project
Here's the code for IdentityServerExtensions.cs:
using System.Collections.Generic;
using IdentityServer3.Core.Configuration;
using IdentityServer3.Core.Services;
using IdentityServer3.Host.Config;
using Microsoft.Owin.Security.Facebook;
using Microsoft.Owin.Security.Google;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.Owin.Security.Twitter;
using Microsoft.Owin.Security.WsFederation;
using IdentityServer3.WsFederation.Configuration;
using IdentityServer3.WsFederation.Models;
using IdentityServer3.WsFederation.Services;
namespace Owin
{
public static class IdentityServerExtension
{
public static IAppBuilder UseIdentityServer(this IAppBuilder app)
{
// uncomment to enable HSTS headers for the host
// see: https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security
//app.UseHsts();
app.Map("/core", coreApp =>
{
var factory = new IdentityServerServiceFactory()
.UseInMemoryUsers(Users.Get())
.UseInMemoryClients(Clients.Get())
.UseInMemoryScopes(Scopes.Get());
factory.CustomGrantValidators.Add(
new Registration<ICustomGrantValidator>(typeof(CustomGrantValidator)));
factory.CustomGrantValidators.Add(
new Registration<ICustomGrantValidator>(typeof(AnotherCustomGrantValidator)));
factory.ConfigureClientStoreCache();
factory.ConfigureScopeStoreCache();
factory.ConfigureUserServiceCache();
var idsrvOptions = new IdentityServerOptions
{
SiteName = "IdentityServer3 plus WsFed IDP / RP",
Factory = factory,
SigningCertificate = Cert.Load(),
PluginConfiguration = ConfigurePlugins,
AuthenticationOptions = new AuthenticationOptions
{
IdentityProviders = ConfigureIdentityProviders,
//EnablePostSignOutAutoRedirect = true
},
//LoggingOptions = new LoggingOptions
//{
// EnableKatanaLogging = true
//},
//EventsOptions = new EventsOptions
//{
// RaiseFailureEvents = true,
// RaiseInformationEvents = true,
// RaiseSuccessEvents = true,
// RaiseErrorEvents = true
//}
};
coreApp.UseIdentityServer(idsrvOptions);
});
return app;
}
private static void ConfigurePlugins(IAppBuilder pluginApp, IdentityServerOptions options)
{
var wsFedOptions = new WsFederationPluginOptions(options);
// data sources for in-memory services
wsFedOptions.Factory.Register(new Registration<IEnumerable<RelyingParty>>(RelyingParties.Get()));
wsFedOptions.Factory.RelyingPartyService = new Registration<IRelyingPartyService>(typeof(InMemoryRelyingPartyService));
pluginApp.UseWsFederationPlugin(wsFedOptions);
}
public static void ConfigureIdentityProviders(IAppBuilder app, string signInAsType)
{
var google = new GoogleOAuth2AuthenticationOptions
{
AuthenticationType = "Google",
Caption = "Google",
SignInAsAuthenticationType = signInAsType,
ClientId = "767400843187-8boio83mb57ruogr9af9ut09fkg56b27.apps.googleusercontent.com",
ClientSecret = "5fWcBT0udKY7_b6E3gEiJlze"
};
app.UseGoogleAuthentication(google);
var fb = new FacebookAuthenticationOptions
{
AuthenticationType = "Facebook",
Caption = "Facebook",
SignInAsAuthenticationType = signInAsType,
AppId = "676607329068058",
AppSecret = "9d6ab75f921942e61fb43a9b1fc25c63"
};
app.UseFacebookAuthentication(fb);
var twitter = new TwitterAuthenticationOptions
{
AuthenticationType = "Twitter",
Caption = "Twitter",
SignInAsAuthenticationType = signInAsType,
ConsumerKey = "N8r8w7PIepwtZZwtH066kMlmq",
ConsumerSecret = "df15L2x6kNI50E4PYcHS0ImBQlcGIt6huET8gQN41VFpUCwNjM"
};
app.UseTwitterAuthentication(twitter);
var adfs = new WsFederationAuthenticationOptions
{
AuthenticationType = "adfs",
Caption = "ADFS",
SignInAsAuthenticationType = signInAsType,
MetadataAddress = "https://adfs.local/federationmetadata/2007-06/federationmetadata.xml",
Wtrealm = "urn:idsrv3rp"
};
app.UseWsFederationAuthentication(adfs);
var aad = new OpenIdConnectAuthenticationOptions
{
AuthenticationType = "aad",
Caption = "Azure AD",
SignInAsAuthenticationType = signInAsType,
Authority = "https://login.windows.net/4ca9cb4c-5e5f-4be9-b700-c532992a3705",
ClientId = "65bbbda8-8b85-4c9d-81e9-1502330aacba",
RedirectUri = "https://localhost:44333/core/aadcb"
};
app.UseOpenIdConnectAuthentication(aad);
}
}
}
For ADFS, you need to add idsrv3 as a RP.
You can get the metadata from https://localhost:44333/core/wsfed/metadata and import into ADFS in the normal fashion.
Once you have done this, you need to change the Endpoints tab in the RP from:
https://localhost:44333/core/wsfed
to
https://localhost:44333/core/external
and you need to add
urn:idsrv3rp
as an extra Identifier in the Identifier tab. This matches the Wtrealm in the code above
The reason you need to change the endpoint is because the two plugins are different (as discussed above). core/wsfed is for downstream, core/external is for upstream.
Now configure the following claims rules:
and
Then run up the MVC application. This should redirect to the idsrv3 Login screen. Click the ADFS button, Authenticate on ADFS. You should be redirected back to the application, click the Contacts tab and you should see the claims displayed.
Enjoy!
3 comments:
Can you explain where CustomGrantValidator and AnotherCustomGrantValidator are illustrated?
Can you point me to where CustomGrantValidator and AnotherCustomGrantValidator are illustrated?
They are part of the core code of identityserver3.
Post a Comment