none
Achieve SSO using Identity Server 3 in MVC RRS feed

  • Question

  • I have set up an identity server 3 in my app. Following is the code:

    public void ConfigureAuth(IAppBuilder app)
        {
            // Configure Identity Server
            // at the identity uri, you are going to find the identity server
            app.Map("/identity", idsrvApp =>
            {
                idsrvApp.UseIdentityServer(new IdentityServerOptions
                {
                    SiteName = "Embedded identity server",
                    //IssuerUri = "https://identitysrv3/embedded", // in real scenarios  make sure this is unique. to uniquely identify users
    
                    Factory = new IdentityServerServiceFactory()
                    .UseInMemoryClients(Clients.Get())
                    .UseInMemoryScopes(Scopes.Get())
                    .UseInMemoryUsers(User.Get()),
    
                    // this is not for SSL, that will be provided by IIS or Azure where we deploy. This is to sign the tokens
                    SigningCertificate = LoadCertificate()
                });
            });        
    
            X509Certificate2 LoadCertificate()
            {
                return new X509Certificate2(
            string.Format(@"{0}\bin\identityServer\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test");
            }
        }

    With this for now I am using inmemory users. Do I have to implement ASP.NET identity to achieve SSO?.

    This is my User class:

    public static List<InMemoryUser> Get()
        {
            return new List<InMemoryUser>()
            {
                new InMemoryUser
                {
                    Username = "Sidd",
                    Password = "secret",
                    Subject = "1",
    
                    Claims = new[]
                    {
                        new Claim(Constants.ClaimTypes.GivenName, "Sidd"),
                        new Claim(Constants.ClaimTypes.FamilyName, "Mehta"),
                    }
                },
                new InMemoryUser
                {
                    Username = "Humpty",
                    Password = "secret",
                    Subject = "3",
    
                    Claims = new[]
                    {
                        new Claim(Constants.ClaimTypes.GivenName, "Humpty"),
                        new Claim(Constants.ClaimTypes.FamilyName, "Sharma"),
                    }
                },
                new InMemoryUser
                {
                    Username = "Virat",
                    Password = "secret",
                    Subject = "4",
    
                    Claims = new[]
                    {
                        new Claim(Constants.ClaimTypes.GivenName, "Virat"),
                        new Claim(Constants.ClaimTypes.FamilyName, "Kohli"),
                    }
                }
            };
        }

    and this is my Clients class:
    public static IEnumerable<Client> Get()
        {
            return new[]
            {
                new Client
                {
                    Enabled = true,
                    ClientName = "Identity Server Web Access",
                    ClientId = "mvc",
                    Flow = Flows.Hybrid,
                    //RequireConsent = true,
    
                    RedirectUris=new List<string>
                    {
                        //"https://localhost:44329/"
                        AppConstants.IdClient,
                        AppConstants.IdClient2
                    },
                    AllowedScopes = new List<string>
                    {
                        "openid",
                        "profile",                        
                    }
                }
            };
        }

    The redirect uri's contains the MVC client application URLs.

    With the identity and users already set, I make my MVC application client. Both the configurations of the application are similar. Following is the code:

    Web Client 2:

    public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
    
            app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions
            {
                AuthenticationType = "Cookies"
            });
    
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId = "mvc",
                Authority = AppConstants.IdSrv,
                RedirectUri = AppConstants.IdClient2,
                SignInAsAuthenticationType = "Cookies",
                ResponseType = "code id_token",
                Scope = "openid",
    
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    MessageReceived = async n =>
                    {
                        EndpointAndTokenHelper.DecodeAndWrite(n.ProtocolMessage.IdToken);
                    }
    
                }
            });
        }

    Web Client 1:
    public void Configuration(IAppBuilder app)
        {
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
    
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();
    
            AntiForgeryConfig.UniqueClaimTypeIdentifier = "unique_user_key";
    
            app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions
            {
                AuthenticationType="Cookies"
            });
    
            app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                ClientId = "mvc",
                Authority = AppConstants.IdSrv,
                RedirectUri = AppConstants.IdClient,
                SignInAsAuthenticationType = "Cookies",
                ResponseType = "code id_token token",
                Scope = "openid profile",
    
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    MessageReceived = async n =>
                    {
                        //EndpointAndTokenHelper.DecodeAndWrite(n.ProtocolMessage.IdToken);
                        //EndpointAndTokenHelper.DecodeAndWrite(n.ProtocolMessage.AccessToken);
    
                        //var userinfo = await EndpointAndTokenHelper.CallUserInfoEndpoint(n.ProtocolMessage.AccessToken);
                    },
    
                    SecurityTokenValidated=async n =>
                    {
                        var userInfo = await EndpointAndTokenHelper.CallUserInfoEndpoint(n.ProtocolMessage.AccessToken);
    
                        var givenNameClaim = new Claim(
                            Thinktecture.IdentityModel.Client.JwtClaimTypes.GivenName,
                            userInfo.Value<string>("given_name"));
    
                        var familyNameClaim = new Claim(
                            Thinktecture.IdentityModel.Client.JwtClaimTypes.FamilyName,
                            userInfo.Value<string>("family_name"));
    
                        //var roles = userInfo.Value<JArray>("role").ToList();
    
                        var newIdentity = new ClaimsIdentity(
                           n.AuthenticationTicket.Identity.AuthenticationType,
                           Thinktecture.IdentityModel.Client.JwtClaimTypes.GivenName,
                           Thinktecture.IdentityModel.Client.JwtClaimTypes.Role);
    
                        newIdentity.AddClaim(givenNameClaim);
                        newIdentity.AddClaim(familyNameClaim);
                    }
    
    
                }
            });            
        }

    want to know what more settings need to be done in order to achieve SSO?. I am able to hit the identity server, input my user credentials, have my redirect uri's in place. When I log to both websites it asks me for user credentials when calling on the [Authorize] attribute in my home controller.

    Any help on how to achieve SSO using above code I have would be great. Currently I am running on a localhost, but I would be putting both websites under one domain only.

    Its very urgent and I need to prepare a demo, so any help quickly would be great.

    Thanks in advance!

    • Moved by CoolDadTx Monday, September 30, 2019 1:53 PM ASP.NET related
    Friday, September 27, 2019 7:27 AM

All replies

  • Hi Siddy Boy,

    Thank you for posting here.

    As far as I know, the identity server 3 has build-in the SSO. So there is no need to write the SSO codes again. I found you just register just one client MVC in your identity server config.

    If you want to implement SSO for multiple MVC application, you should update the client list in the identity server and create the validate method in the MVC.

    Details ,you could refer to this article:

    IdentityServer3

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, September 30, 2019 9:50 AM
  • Please post questions related to MVC in the ASP.NET forums.

    Michael Taylor http://www.michaeltaylorp3.net

    Monday, September 30, 2019 1:53 PM
  • Hey thanks for the reply. But if you check my Clients class I have already added another redirect uri of my webclient2.

    If you mean I need to add one more client like:

    return new[] { new Client { Enabled = true, ClientName = "Identity Server Web Access", ClientId = "mvc", Flow = Flows.Hybrid, //RequireConsent = true, RedirectUris=new List<string> { //"https://localhost:44329/" AppConstants.IdClient }, AllowedScopes = new List<string> { "openid", "profile", } },

    new Client
                {
                    Enabled = true,
                    ClientName = "Identity Server Web Access 2",
                    ClientId = "mvc 2",
                    Flow = Flows.Hybrid,
                    //RequireConsent = true,
    
                    RedirectUris=new List<string>
                    {
                        //"https://localhost:44329/"                    
                        AppConstants.IdClient2
                    },
                    AllowedScopes = new List<string>
                    {
                        "openid",
                        "profile",                        
                    }
                }

    };

    then it throws me an error.

    So how do we add 2 clients in order to achieve sso?


    • Edited by Siddy Boy Wednesday, October 2, 2019 11:37 AM
    Wednesday, October 2, 2019 11:09 AM