3

Can we make custom login page for identity server users with SharePoint? My SharePoint site has users of Identity server. I want to make custom login page which allow to login active directory users and Identity server users.

  • Do you want to edit SharePoint login page or Identity server login page? – love thakker May 19 '16 at 13:51
  • I want custom login page for sharepoint which enables login for identity server users from same page.I dont want to redirect to Identity server's login page from Custom sharepoint login page. – Jay Shah May 19 '16 at 13:55
2

I don’t think this is directly possible to have a custom login form for Active Directory users. But there is a tricky way.

You can go with Form Based Authentication and let FBA to connect with your Active Directory.

For more information on Connecting FBA to Active Directory please have look to this :

Setting up Forms Based Authentication for Active Directory

Let me know your thoughts.

| improve this answer | |
  • Thanks for your concern Aakash. I know we can make custom login page for FBA. But I want to make login for Identity server users from custom login page. – Jay Shah May 19 '16 at 14:02
1

You need to use below sample code to get token for Identity server login.

Add below code to your login button. Currently it will pop up claim that return through Identity server.

public void SignIn(string user, string pass)
        {
            try
            {
                //Call the _authorizer to check the credentials
                if (_authorizer.Authorize(user, pass, true))
                {
                    //Checks if the pasword is expired, usually a rediriect or message if so
                    if (_authorizer.IsExpired) { } 
                    var claims = string.Empty;

                    var identity = (IClaimsIdentity)HttpContext.Current.Session["Claims"];

                    //Building a claims string
                    foreach (var claim in identity.Claims)
                        claims += claim + "\\n\\n" ;

                    //An example of how we pass claims around
                    this.Page.ClientScript.RegisterStartupScript(Page.GetType(), "myalert", "alert('Claims Passed:\\n\\n" + claims + "');", true);

                }

            }
            catch (Exception e)
            {
               throw e;
            }
        }

you need to include Microsoft.IdentityModel namespace in your reference.

Now create a class name Authorizer. Include below namespace:

using System.IdentityModel.Tokens;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Web;
using System.Xml;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Protocols.WSTrust;
using Microsoft.IdentityModel.Protocols.WSTrust.Bindings;
using Microsoft.IdentityModel.SecurityTokenService;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Web; 

Add below code in to it.

//Token holds the identifier and token expiration information
        public virtual SecurityToken Token
        {
            get
            {
                return (SecurityToken)HttpContext.Current.Session["SessionToken"];
            }
            set
            {
                HttpContext.Current.Session["SessionToken"] = value;
            }
        }

        //Identity holds all the identity info for a user i.e. token, IsAuthenticated, and all the CLAIMS information
        public virtual IClaimsIdentity Identity
        {
            get
            {
                return (IClaimsIdentity)HttpContext.Current.Session["Claims"];
            }
            set
            {
                HttpContext.Current.Session["Claims"] = value;
            }
        }

        //Start the authorization process
        public bool Authorize(string userName, string password, bool initializedByUser)
        {
            //Create a channel factory that will manifest the channel we need for token issuing
                //Here we point it to the IdentityServerEndpoint property, this tells the channel who the token issuer is, which is Identity Server 
            var factory = new WSTrustChannelFactory(
                new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
                IdentityServerEndpoint());

            //Set all the needed info for the channel
            factory.TrustVersion = TrustVersion.WSTrust13;
            factory.Credentials.UserName.UserName = userName;
            factory.Credentials.UserName.Password = password;
            factory.Credentials.SupportInteractive = false;
            //Create channel
            factory.ConfigureChannelFactory();
            var channel = factory.CreateChannel();

            return Authorize(channel);

        }

        /// <summary>
        /// This will create the token and validate the user, this will recieve all the user identity info e.g. the Claims
        /// </summary>
        /// <param name="channel"></param>
        /// <returns></returns>
        private bool Authorize(IWSTrustChannelContract channel)
        {
            var rst = new RequestSecurityToken
            {
                RequestType = RequestTypes.Issue,
                AppliesTo = new EndpointAddress(//end point address), // you will get this from Identity server
                KeyType = KeyTypes.Bearer
            };

            try
            {
                //Returns the token from Identity Server
                var genericToken = channel.Issue(rst) as GenericXmlSecurityToken;

                //Customize token handler settings
                FederatedAuthentication.ServiceConfiguration.SaveBootstrapTokens = true;
                FederatedAuthentication.ServiceConfiguration.AudienceRestriction.AudienceMode = System.IdentityModel.Selectors.AudienceUriMode.Never;
                FederatedAuthentication.ServiceConfiguration.CertificateValidationMode = X509CertificateValidationMode.None;
                FederatedAuthentication.ServiceConfiguration.RevocationMode = X509RevocationMode.NoCheck;
                FederatedAuthentication.ServiceConfiguration.IssuerNameRegistry = new ClientCertificateIssuerNameRegistry();

                var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
                //Pull what we need from the generic token
                var token = handlers.ReadToken(new XmlTextReader(new StringReader(genericToken.TokenXml.OuterXml)));
                //Validates the token and adds the user identity info (claims) if valid
                var identity = handlers.ValidateToken(token).First();

                Token = token;
                Identity = identity;

                return true;
            }
            catch (SecurityNegotiationException noTrust)
            {
                throw new FaultException("The Identity Server is using an untrusted SSL Certificate.  You must trust this certificate to continue.  Further details are in the installation guide.");
            }
            catch (SecurityTokenValidationException noTrustedPeople)
            {
                // This is a more specific version of the above error, but gives perfect instructions on how to fix it so we pass it up. (also in the install guide)
                throw;
            }
            catch (EndpointNotFoundException notConnected)
            {
                throw new FaultException("The Identity Server could not be reached, please check your internet connection.");
            }
            catch (CommunicationException connectionDropped)
            {
                throw new FaultException("The user name or password you entered is not correct.  Please check the values and try again.");
            }
            catch (Exception)
            {
                throw;
            }
        }

        //Checks the claims for an expried password claim
        public bool IsExpired
        {
            get
            {
                return Identity.Claims.SingleOrDefault<Claim>(claim => claim.ClaimType.Equals("https://" + Identity server site URL +"/claims/passwordexpired")) != null;
            }
        }

        public void SignOut()
        {
            Token = null;
            Identity = null;
        }

        //Uses the URL defined in the web.config "IdentityServerAddress" property to create the address for token issuing
        private EndpointAddress IdentityServerEndpoint()
        {
            return new EndpointAddress("https://" + Identity server site URL  + "/IdentityServer/issue/wstrust/mixed/username");
        }
    }

    //Handles certificate verification
    public class ClientCertificateIssuerNameRegistry : IssuerNameRegistry
    {
        public override string GetIssuerName(SecurityToken securityToken)
        {
            if (securityToken == null)
            {
                throw new ArgumentNullException("securityToken");
            }

            X509SecurityToken token = securityToken as X509SecurityToken;
            if (token != null)
            {
                return token.Certificate.Thumbprint;
            }

            return null;
        }
    }

This code works for me.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.