Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Federated IdentityProvider with Passive Login #604

Closed
ghilios opened this issue Dec 2, 2014 · 3 comments
Closed

Federated IdentityProvider with Passive Login #604

ghilios opened this issue Dec 2, 2014 · 3 comments
Labels

Comments

@ghilios
Copy link

ghilios commented Dec 2, 2014

Hey, I'm having one hell of a time trying to this scenario to work. I am trying to set up IdentityServer v3 to use Azure AD as the only IdentityProvider, transform and enrich claims (ie, by calling GraphAPI) and then using that token instead.

My setup:

  1. Relying Party app hosting a Web Api. https://localhost/SampleApp
  2. Identity Server instance hosted on https://localhost/StsWithAdfs/auth (ignore the Adfs naming)
  3. An Azure AD instance. I added an Application with App URI https://msedge.corp.microsoft.com/SDK that redirects to https://localhost/StsWithAdfs/auth/.

When I issue a request to /SampleApp/api/Values, it redirects to /StsWithAdfs/auto/wsfed?wtrealm... and then to /StsWithAdfs/auth/login?signin=... At no point does it seem to redirect to Azure AD. I always get stuck at an IdentityServer login screen asking for user name and password (ie, not my Azure AD creds). Is it also possible to get this to passively authenticate with Azure AD without any interaction from the user? In case it helps, below is the code I've been cobbling together. Perhaps I'm mixing my "Client" and "RelyingParty" concepts also, but I've tried various combinations to no avail.

Thanks for any help you can provide. I've been bashing my head against the desk for 3 days now!

Code for /StsWithAdfs

        public void Configuration(IAppBuilder app)
        {
            app.Map(
                "/auth",
                idSrv =>
                    {
                        var factory = InMemoryFactory.Create(
                            users: Enumerable.Empty<InMemoryUser>(),
                            scopes: StandardScopes.All,
                            clients: new Client[]
                                         {
                                             new Client()
                                                 {
                                                     ClientName = "client",
                                                     Enabled = true,
                                                     ClientId = "clientid",
                                                     Flow = Flows.AuthorizationCode,
                                                     ClientUri = "https://msedge.corp.microsoft.com/SDK",
                                                     RedirectUris = new List<Uri>()
                                                                        {
                                                                            new Uri("https://hiliosdev.corp.microsoft.com/SampleApp")
                                                                        },
                                                    IdentityTokenSigningKeyType = SigningKeyTypes.Default
                                                 }
                                         });
                        var cert = GetCertificate("CN=HILIOSDEV.redmond.corp.microsoft.com");

                        var options = new IdentityServerOptions
                                          {
                                              IssuerUri = "https://hiliosdev.corp.microsoft.com/StsWithAdfs",
                                              SiteName = "Edge SDK",
                                              SigningCertificate = cert,
                                              Factory = factory,
                                              PluginConfiguration = ConfigurePlugins,
                                              AuthenticationOptions = new AuthenticationOptions()
                                                                          {
                                                                              IdentityProviders = (appSrv, str) =>
                                                                                  {
                                                                                      appSrv.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);
                                                                                      var ws = new WsFederationAuthenticationOptions()
                                                                                                   {
                                                                                                       MetadataAddress = "https://login.windows.net/689264f3-0b7f-4b2d-ab44-a65c27be2ac8/FederationMetadata/2007-06/FederationMetadata.xml",
                                                                                                       Wtrealm = "https://msedge.corp.microsoft.com/SDKPrototype",
                                                                                                       SignInAsAuthenticationType = str,
                                                                                                       AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType,
                                                                                                   };
                                                                                      appSrv.UseWsFederationAuthentication(ws);
                                                                                  },
                                                                                  EnableLocalLogin = false
                                                                          }
                                          };

                        idSrv.UseIdentityServer(options);
                    });
        }

        private void ConfigurePlugins(IAppBuilder pluginApp, IdentityServerOptions options)
        {
            var relyingParties = new List<RelyingParty>();
            /* var relyingParties = new List<RelyingParty>
            {   
                new RelyingParty
                {
                    Realm = "https://msedge.corp.microsoft.com/SDK",
                    Name = "Test App",
                    Enabled = true,
                    ReplyUrl = "https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/",
                    TokenType = Thinktecture.IdentityModel.Constants.TokenTypes.JsonWebToken,
                    TokenLifeTime = 1,

                    ClaimMappings = new Dictionary<string,string>
                    {
                        { "sub", ClaimTypes.NameIdentifier },
                        { "given_name", ClaimTypes.Name },
                        { "email", ClaimTypes.Email }
                    }
                }
            };
            */

            var wsFedOptions = new WsFederationPluginOptions
            {
                IdentityServerOptions = options,
                Factory = new WsFederationServiceFactory
                {
                    UserService = options.Factory.UserService,
                    RelyingPartyService = Registration.RegisterFactory<IRelyingPartyService>(() => new InMemoryRelyingPartyService(relyingParties))
                },
                MetadataEndpoint = new EndpointSettings() { IsEnabled = true }
            };

            pluginApp.UseWsFederationPlugin(wsFedOptions);
        }

Code for /SampleApp

    {
        public void ConfigurationAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
            });

            app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
            {
                MetadataAddress = "https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/wsfed/metadata",
                Wtrealm = "https://msedge.corp.microsoft.com/SDK"
            });

            ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
        }
@ghilios
Copy link
Author

ghilios commented Dec 3, 2014

I'm close I think. If I wipe my cookies and not use Fiddler for the initial request, it goes through login.windows.net each time. It doesn't ultimately redirect back to the originating Web Api endpoint though (/SampleApp/api/Values). Rather, it goes back to /StsWithAdfs/auth and redirects to /StsWithAdfs/auth/callback where it ends. Below is a summary

  1. GET https://hiliosdev.corp.microsoft.com/SampleApp/api/Values
    302 Redirect to https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/wsfed?wtrealm=https%3a%2f%2fmsedge.corp.microsoft.com%2fSDK&wctx=WsFedOwinState%3dF9QFmkPNOxaoRsMdv7Ag0Z2rcDGo226uAIHMcK0PpK3dNaxDVK55NwFgfcYtU6gFCjTOdtHBI11mEpkRTeGeqyGyMjsG4gYCVhEULSjydBIoiZST_s3bGnq9AwnTQPaS3rq0jY8_07u3RenZscWPpGK4d_vCvTA6ORNtHqqOvkA&wa=wsignin1.0
  2. GET https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/wsfed?wtrealm=https%3a%2f%2fmsedge.corp.microsoft.com%2fSDK&wctx=WsFedOwinState%3dF9QFmkPNOxaoRsMdv7Ag0Z2rcDGo226uAIHMcK0PpK3dNaxDVK55NwFgfcYtU6gFCjTOdtHBI11mEpkRTeGeqyGyMjsG4gYCVhEULSjydBIoiZST_s3bGnq9AwnTQPaS3rq0jY8_07u3RenZscWPpGK4d_vCvTA6ORNtHqqOvkA&wa=wsignin1.0
    302 Redirect to https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/login?signin=9802c0d7bfec44c9a6f9fa980f0daf16
  3. GET https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/login?signin=9802c0d7bfec44c9a6f9fa980f0daf16
    302 Redirect to https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/external?provider=Federation&signin=9802c0d7bfec44c9a6f9fa980f0daf16
  4. GET https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/external?provider=Federation&signin=9802c0d7bfec44c9a6f9fa980f0daf16
    302 Redirect to https://login.windows.net/689264f3-0b7f-4b2d-ab44-a65c27be2ac8/wsfed?wtrealm=https%3a%2f%2fmsedge.corp.microsoft.com%2fSDKPrototype&wctx=WsFedOwinState%3d8vFvcHOM3fNy95-pbmbKvH-zEjRamb1H695yfhPoYMSm9VKj_tACsVLoCEzCW0yW8R15DW7nQ4NWxTFW7gw8jvta4ce6oz5GbRarHceFfUxMXZ4-1GSOxGRS_z0IdycOaZ4cWrlY-I6ZYu2B61Fp1nsojkACuNBxFBmoCOC_uDlit12C27ubHL2r9GKICsQuWSnATDJzC0OstPbestb4kBH2MvPR9mkgjFESzzrulqo&wa=wsignin1.0
  5. GET https://login.windows.net/689264f3-0b7f-4b2d-ab44-a65c27be2ac8/wsfed?wtrealm=https%3a%2f%2fmsedge.corp.microsoft.com%2fSDKPrototype&wctx=WsFedOwinState%3d8vFvcHOM3fNy95-pbmbKvH-zEjRamb1H695yfhPoYMSm9VKj_tACsVLoCEzCW0yW8R15DW7nQ4NWxTFW7gw8jvta4ce6oz5GbRarHceFfUxMXZ4-1GSOxGRS_z0IdycOaZ4cWrlY-I6ZYu2B61Fp1nsojkACuNBxFBmoCOC_uDlit12C27ubHL2r9GKICsQuWSnATDJzC0OstPbestb4kBH2MvPR9mkgjFESzzrulqo&wa=wsignin1.0
    200 OK (text/html)
  6. POST https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/
    302 Redirect to /StsWithAdfs/auth/callback
  7. GET https://hiliosdev.corp.microsoft.com/StsWithAdfs/auth/callback
    200 OK (text/html)

@brockallen
Copy link
Member

Ok, I see you have disabled local login.... so now you are getting back to IdentityServer from AAD, yes? So perhaps your katana middleware in the RP simply isn't monitoring the callback URL being submitted to.

@ghilios
Copy link
Author

ghilios commented Dec 4, 2014

Ahh I finally figured this out. The issue is in the InMemoryUserService. When authorizing the external user, it looks for a "name" claim. Azure AD only returns givenname and surname claims, so the authorization fails. I got around this by providing my own IUserService implementation that uses the oid claim instead, which I'll then use in GetProfileAsync to query Graph API for the email address and other claims.

Thanks for looking!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants