Showing posts with label IdentityServer. Show all posts
Showing posts with label IdentityServer. Show all posts

Wednesday, February 27, 2019

IdentityServer: IResourceOwnerPasswordValidator

I was looking at idsrv4 and how to integrate it with a custom user store. In this case it was SQL Server.

idsrv4 uses .NET Core 2.2 but a lot of the samples I found were for earlier versions of .Net Core.

Some of the samples used IUserService but I couldn't find that.

So Mr Google to the rescue.

e.g.

https://stackoverflow.com/questions/35304038/identityserver4-register-userservice-and-get-users-from-database-in-asp-net-core

"In IdentityServer4. IUserService is not available anymore, now you have to use IResourceOwnerPasswordValidator to do the authentication and to use IProfileService to get the claims."

The problem I have with this is that Resource Owner Password is not just a random method name. It's the name of an OAuth flow! Most people don't realise this.

My client used implicit flow. Using IResourceOwnerPasswordValidator makes no sense.

So  you can just use a controller to authenticate the user like the AccountController.

Enjoy!

Wednesday, October 18, 2017

IdentityServer : WS-Fed metadata imported into ADFS

I've been looking at Identity server 4 (idsrv4) just to have a play with it.

This runs on .NET Core which I something else I need to get up to speed on.

There is also a WS-Fed plug-in which I got working and tried to hook up to ADFS as an exercise.

The metadata endpoint is:

http://localhost:5000/wsfederation

and when I tried to import this into ADFS, I got the normal:

"Metadata contains some features not supported by ADFS" warning.

Now this could be because the metadata contains a SAML profile that ADFS doesn't support - PAOS being an example.

But 999 out of 1000 times, it's because the endpoints are "http" not "https".

Looking at the metadata, this is indeed the case.

This means that although the entry is added to ADFS, it has no endpoints so it will never work.

You can't just edit the metadata because it's signed and you'll get a signing error when you try and import the updated file.

You can delete the whole "Signature" section in the XML if you want. Do this at your own risk - normal best practice security applies :-).

The other way is to update the metadata when it's generated. There is no metadata file - it's dynamically generated every time.


You can do this in the "Properties".

Select the "Enable SSL" check box. IIS Express generates a new endpoint as above so now you have to replace all the instances of:

http://localhost:5000

with the https endpoint as above.

This also means that you need to change this address in any of the client samples.

The new metadata imports without issues.

Enjoy!

Thursday, June 09, 2016

Azure B2C : Integration with IdentityServer

This post covered an overview of Azure Active Directory (AD) B2C and described some of the gotchas.

Imagine you have purchased a SaaS application that supports "normal" OpenID Connect. The vendor has quoted a ridiculous price to add the profile support necessary for the SaaS application to connect to Azure B2C.

One way around this (as you guessed from the title!)  is to add IdentityServer into the mix.

The path would then be:

SaaS application --> normal OIDC --> IdentityServer --> add profile info. to OIDC --> Azure B2C

The Azure AD B2C sample is Azure AD B2C preview: Build a .NET web app.

We need to add Azure B2C to IdentityServer as an external OIDC CP.

The SaaS application is added to IdentityServer as an OIDC RP.

For simplicity, just sign-in is covered. I'm assuming the user has already registered themselves.

As usual, here is the gist.

(Note that this is still a work in progress. Some B2C claims are not being passed through. I'm still investigating that. Hopefully, this does provide some guidance).

To test this out, I used this sample as the SaaS application. This uses "normal OIDC" to talk to IdentityServer.

The B2C sign-in profile is configured to allow local account login plus Facebook.

When the user clicks Sign-In in the application. they see this IdentityServer HRD screen.


The user selects "Azure B2C".

They then get redirected to B2C and:


They select "Local Account SignIn" and enter their credentials.

They are then redirected back to the application and see their claims.


To expand this into "SignUp", "Edit Details", "Reset Password" etc. you could have some more buttons on the HRD screen each tied into a different B2C profile.

However, this assumes that all applications will have the same set of authentication providers. For the case where some applications use Facebook only, some use local and Twitter etc. there will have to be some kind of mapping table mapping applications to providers.

And some of you will be asking "What about SaaS applications that use WS-Fed or SAML?". Good question, that was another reason to add IdentityServer into the mix and that is the subject of another post.

Enjoy!

Wednesday, December 16, 2015

IdentityServer : The WebApp-OpenIDConnect-DotNet Azure AD sample

I use this sample a lot - Azure-Samples/active-directory-dotnet-webapp-openidconnect.

I've also been looking at idsrv3 lately - mainly from the enterprise PoV i.e. WS-Fed and SAML

idserv3 also supports modern authentication i.e. OpenID Connect and OAuth2.

So I wondered if this sample would work on idsrv3?

As per OpenID Connect Hybrid Flow and IdentityServer v3:

"Lastly, hybrid flow is the only flow supported by the Microsoft OpenID Connect authentication middleware (in combination with a form post response mode)"

Hybrid flow is described in the article. The above tells us that idsrv3 has to be hooked up using the hybrid flow.

(BTW - the idsrv3 equivalent sample is here - Clients/MVC OWIN Client (Hybrid)).

Turns out the changes are minimal - as you would expect.

In Startup.Auth.cs:

private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];

string authority = String.Format(CultureInfo.InvariantCulture, aadInstance);

public void ConfigureAuth(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType
        (CookieAuthenticationDefaults.AuthenticationType);
    
    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    app.UseOpenIdConnectAuthentication( 
        new OpenIdConnectAuthenticationOptions
        {
            ClientId = clientId,
            Authority = authority,
            RedirectUri = postLogoutRedirectUri,
            PostLogoutRedirectUri = postLogoutRedirectUri,
            Notifications = new OpenIdConnectAuthenticationNotifications


The only change was to add the RedirectUri.

Note that I tried to minimise the changes so I kept the AADInstance variable even though Azure AD is not involved.

web.config:

<add key="ida:ClientId" value="katanaclientad" />
<!--<add key="ida:Tenant" value="[Enter tenant name, e.g. contoso.onmicrosoft.com]" />-->
<add key="ida:AADInstance" value="https://localhost:44333/core" />
<add key="ida:PostLogoutRedirectUri" value="https://localhost:44320/" />

On the idsrv3 side, we need a new Client:

Host-Configuration/Client.cs

new Client
{
    ClientName = "Katana Hybrid Client Demo - AAD Sample",
    Enabled = true,
    ClientId = "katanaclientad",
    ClientSecrets = new List<Secret>
    { 
        new Secret("secret".Sha256())
    },

    Flow = Flows.Hybrid,
                    
    AllowedScopes = new List<string>
    {
        Constants.StandardScopes.OpenId,
        Constants.StandardScopes.Profile,
        Constants.StandardScopes.Email,
        Constants.StandardScopes.Roles,
        Constants.StandardScopes.OfflineAccess,
        "read",
        "write"
    },
                    
    ClientUri = "https://identityserver.io",
    LogoUri = [snip]

    RequireConsent = false,
    AccessTokenType = AccessTokenType.Reference,
                    
    RedirectUris = new List<string>
    {
        //"http://localhost:2672/",
        "https://localhost:44320/",
    },

    PostLogoutRedirectUris = new List<string>
    {
        //"http://localhost:2672/"
        "https://localhost:44320/",
    }
},

The changes to display the claim are as per: IdentityServer : Identity Server 3 as a WS-Federation IDP with an ASP.NET MVC application.

 So we navigate to the sample, click the "Sign In" link. it redirects to idsrv3, we can authenticate with "alice / alice" or "bob / bob", back to the sample, click the Contact tab and the claims are displayed as below:

Claim Type Claim Value
nonce 635858209323.....Tk5YjYtNjU1NzU2ZWU4MzU5
iat 1450224140
c_hash 0ibKE6.....uZcbGR_A
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier 818727
http://schemas.microsoft.com/claims/authnmethodsreferences password
http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant 1450224139
http://schemas.microsoft.com/identity/claims/identityprovider idsrv
name Alice Smith
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname Alice
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname Smith
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage http://alice.com
iss https://localhost:44333/core
aud katanaclientad
exp 1450224440
nbf 1450224140

Enjoy!

Friday, December 11, 2015

IdentityServer : The power of extensibility

The previous post compared idsrv3 to other Microsoft Identity products from a protocol perspective.

From a wider perspective, a key point is that it is extensible.

ADFS 2.x ran on IIS and was essentially a web application.

This meant you had access to the form code, css and html. As a result, you could extend ADFS by hiding providers in the HRD, adding MFA, allowing different kinds of user names, displaying why authentication failed e.g. account lockout and so on.

However, it resulted in a number of "insecure" installations and so the architecture of ADFS 3.0 onwards changed to a black box running on http.sys (and thus no IIS) with very limited customisation. 

ADFS and Azure AD are pretty much locked down and there is a good argument for supporting this approach.

idsrv3 takes the opposite approach - it is designed to be extensible and supports plugging in Katana middleware.

Katana allows you to pick and choose functionality you want - both vertically (the ASP.NET framework) and horizontally (you can mix and match authentication e.g. FBA, WS Fed, SAMLp and certificate in the same application).

In addition, it's open source so you can enhance it any way you like e.g. custom login workflows / registration etc. Ideally, all the enhancements should be done using the extensibility points rather than altering the code.

I've used it in a number of projects to essentially extend ADFS by federating ADFS and idsrv3 and then "altering" and "extending" on the upstream and downstream paths.

Unlike ADFS, idsrv3 has no dependency on AD. It does not need to be installed on a domain controller and can be hosted in IIS, NT Services, embedded, on-premises or in the cloud on Azure or AWS.

However, with great power comes great responsibility. idsrv3 is a certified security product.

Review any changes you make from a security point of view.

Enjoy!

Wednesday, December 09, 2015

IdentityServer : Comparing IdentityServer to other Microsoft Identity products

I've just done a series of posts on IdentityServer 3 and I thought it would be a good idea to sum it all up.

I'm looking at the protocols supported for purpose of comparison.



Identity Server 3
Azure AD
ADFS 3.0
(2012 R2)
ADFS 4.0? (2016 vNext)





Authenticate against
In Memory
ASP.NET Identity
Membership Reboot
(interface can be extended to any repository)
Azure AD Graph
AD
AD
LDAP v3
SQL Server





WS-Federation
Y
(via Katana extension)
Y
Y
Y





SAML 2.0
Y
(via Katana extension)
Y
Y
Y





OpenID Connect
Y
Y
N
Y





OAuth 2.0
Y
All profiles

Y
All profiles

Y
Authorisation Code Grant confidential client profile only
Y
All profiles






Social
Google
Twitter
Facebook
(can be extended via Katana extension)
Azure ACS / B2C
Via federation with Azure ACS / B2C
Via federation with Azure ACS / B2C


 


Azure ACS = Windows Live / Google / Yahoo / Facebook

Azure B2C = Facebook / Google+ / Amazon / Linkedin

As you can see, IS compares really well and offers a wider selection than ADFS 3.0.

See also: IdentityServer : The power of extensibility

Enjoy!

Tuesday, December 08, 2015

IdentityServer : ASP.NET MVC application to idsrv3 to ADFS via SAMLp 2.0

This continues the series of blogs I've done on IdentityServer 3.

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 --> WS-Fed --> IS --> SAMLp 2.0 --> ADFS

Normally you would federate to ADFS via WS-Fed. However, in this scenario I want to use the
Kentor.AuthServices SAMLp stack so I'm using ADFS as a SAMLp IDP.

ADFS is v3.0. IS is version 3. This is being invoked by the Host.Web sample in idsrv3.

This builds on  IdentityServer : ASP.NET MVC application to idsrv3 to Kentor.AuthServices via SAMLp 2.0

Note by SAMLp 2.0 I mean the SAML protocol, not the SAML token.

The code in IdentityServerExtension.cs in the Host.Configuration project of idsrv3 would look like:

var authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
{
    SPOptions = new SPOptions
    {
        EntityId = new EntityId("http://localhost:44333/core")
    },

    SignInAsAuthenticationType = signInAsType,
    AuthenticationType = "saml2p",
    Caption = "SAML2p",
};

Uri metadataURI = new Uri("https://adfs.local/federationmetadata/2007-06/federationmetadata.xml");

authServicesOptions.IdentityProviders.Add(new IdentityProvider(
    new EntityId("http://adfs.local/adfs/services/trust"),
    authServicesOptions.SPOptions)
    {
        MetadataUrl = metadataURI,
        LoadMetadata = true,
    });

app.UseKentorAuthServicesAuthentication(authServicesOptions);

Now we need to configure ADFS. The idsrv3 metadata at core/wsfed/metadata refers only to WS-Fed not to SAMLp so we need to do this manually.

From the ADFS side, idsrv3 is a RP so we need to add a new RP.

Identifier tab:


We can leave out the certificates for the purposes of this exercise.

Endpoint tab:


where the second endpoint is:

https://localhost:44333/core/AuthServices/Acs

Under the Advanced tab, set the hash algorithm to SHA-1.

The claims rule mappings are exactly the same as per:

IdentityServer : ASP.NET MVC application to idsrv3 to ADFS

Then run up the MVC application. This should redirect to the idsrv3 Login screen. Click the SAML2p button, Authenticate on ADFS. You should be redirected back to the application, click the Contacts tab and you should see the claims displayed

If you want to see the actual SAML messages, use the excellent SAML tracer.

Enjoy!

IdentityServer : ASP.NET MVC application to idsrv3 to Kentor.AuthServices via SAMLp 2.0

This continues the series of blogs I've done on IdentityServer 3.

This scenario involves idsrv3 as both an IDP to an ASP.NET MVC application and as a RP to Kentor.AuthServices. Also I'm using the InMemory option.

So the authentication chain is:

RP --> WS-Fed --> IS --> SAMLp 2.0 --> Kentor.AuthServices

IS is version 3. This is being invoked by the Host.Web sample in idsrv3.

This builds on IdentityServer : ASP.NET MVC application to idsrv3 to ADFS. 

Note by SAMLp 2.0 I mean the SAML protocol, not the SAML token.

You need these NuGet packages:

Kentor.AuthServices

Kentor.AuthServices.Owin

Refer to the idsrv3 documentation.

The code in IdentityServerExtension.cs in the Host.Configuration project of idsrv3 would look something like:

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 authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
{
    SPOptions = new SPOptions
    {
        EntityId = new EntityId("http://sp.example.com")
    },

    SignInAsAuthenticationType = signInAsType,
    AuthenticationType = "saml2p",
    Caption = "SAML2p",
};

authServicesOptions.IdentityProviders.Add(new IdentityProvider(
    new EntityId("http://stubidp.kentor.se/Metadata"),
    authServicesOptions.SPOptions)
    {
        LoadMetadata = true,
    });

app.UseKentorAuthServicesAuthentication(authServicesOptions);

Note the ADFS section is just for context.

You need the following includes:

    using Kentor.AuthServices;
    using Kentor.AuthServices.Owin;
    using System.IdentityModel.Metadata;

You do not need to make any changes to the app / web.config.

The link in the code above viz. http://stubidp.kentor.se/Metadata points to a test SAMLp IDP which is a cool idea,

Then run up the MVC application. This should redirect to the idsrv3 Login screen. Click the SAML2p button, Authenticate on the test IDP (you can select different users from the dropdown). . You should be redirected back to the application, click the Contacts tab and you should see the claims displayed.

If you want to see the actual SAML messages, use the excellent SAML tracer.

Enjoy!

Monday, December 07, 2015

IdentityServer : ASP.NET MVC application to idsrv3 to Azure Active Directory

This builds on  my previous post IdentityServer : ASP.NET MVC application to idsrv3 to ADFS but in this case we are going to use Azure AD (AAD) instead of ADFS.

This scenario involves idsrv3 as both an IDP to an ASP.NET MVC application and as a RP to AAD. Also I'm using the InMemory option.

So the authentication chain is:

RP --> IS --> AAD

IS is version 3. Everything is via WS-Fed.

I am doing this direct on idsrv3.

You should read the previous post to get the basics.

For this scenario, comment out the ADFS entry and add the AAD one as below. (don't be confused by the existing AAD entry - that's for OpenID Connect).

/*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 aadfed = new WsFederationAuthenticationOptions
{
    AuthenticationType = "aadfed",
    Caption = "Azure AD Fed",
    SignInAsAuthenticationType = signInAsType,

    MetadataAddress = "https://login.microsoftonline.com/xxx/federationmetadata/2007-06/federationmetadata.xml",
    Wtrealm = "https://localhost:44333/core/external/"
};

app.UseWsFederationAuthentication(aadfed);

Now we have to configure the AAD application. The steps to get your own AAD tenant etc. are extensively documented elsewhere and out of scope for this post.

In the AAD portal, in the AD tab on the left, click on "Applications" and click "Add" at the bottom.

The name can be anything.

Sign-On URL = https:/localhost:44333/core/external/
App ID URI =   https:/localhost:44333/core/external/
Reply URL =     https:/localhost:44333/core/external/

Then save the Application.

Now click on the application in the Application list and click on "View Endpoints" at the bottom.

Copy the "Federation Metadata Document" URL and paste it in the MetadataAddress in the code above.

Then run up the MVC application. This should redirect to the idsrv3 Login screen. Click the "Azure AD Fed" button, Authenticate on AAD. You should be redirected back to the application, click the Contacts tab and you should see the claims displayed.

Enjoy!

Friday, December 04, 2015

IdentityServer : ASP.NET MVC application to idsrv3 to ADFS

This continues the series of blogs I've done on IdentityServer 3.

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&lt;ICustomGrantValidator>(typeof(CustomGrantValidator)));
                factory.CustomGrantValidators.Add(
                    new Registration&lt;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&lt;IEnumerable&lt;RelyingParty>>(RelyingParties.Get()));
            wsFedOptions.Factory.RelyingPartyService = new Registration&lt;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!