public ClaimsPrincipal Transform(ClaimsPrincipal principal, IDictionary <string, string> inputs, IExternalClaimTransformationPipelineContext pipelineContext)
        {
            if (principal == null)
            {
                throw new ArgumentNullException("principal");
            }

            try
            {
                var identity = principal.Identities.FirstOrDefault(x => x.BootstrapContext != null);

                if (identity == null)
                {
                    identifyLogWriter.WriteDebug("No Identify has BootstrapContext");
                    return(principal);
                }

                var bootstrapContext = identity.BootstrapContext as BootstrapContext;
                if (bootstrapContext == null)
                {
                    identifyLogWriter.WriteDebug("The identity.BootstrapContext object is not of BootstrapContext type.");
                    return(principal);
                }
                identifyLogWriter.WriteDebug("The identity.BootstrapContext is valid");
            }
            catch (InvalidOperationException ex)   // this exception type is caught for illustration purpose only
            {
                // Ids from 4830 to 4899 are reserved for external components. Pick one that doesn't conflict with other external events in the same set up
                identifyLogWriter.WriteError(4830, ex);
            }

            return(principal);
        }
Ejemplo n.º 2
0
 private bool VerifyIfUserNameIsCorrect(string username, IIdentifyLogWriter logWriter)
 {
     if (username.Equals("unknownusername", StringComparison.InvariantCultureIgnoreCase))
     {
         logWriter.WriteError($"Incorrect passord {username}");
         return(false);
     }
     return(true);
 }
Ejemplo n.º 3
0
 private bool VerifyPasswordIsCorrect(string password, IIdentifyLogWriter logWriter)
 {
     if (password.Equals("incorrectpassword", StringComparison.InvariantCultureIgnoreCase))
     {
         logWriter.WriteError($"Incorrect passord {password}");
         return(false);
     }
     return(true);
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Validate credentials by generic provider
        /// </summary>
        /// <param name="cc">Notice that on STs the controller context is irrelevant</param>
        /// <param name="inputs"></param>
        /// <param name="logWriter"></param>
        /// <returns></returns>
        public CredentialsValidationResult Validate(ControllerContext cc, IDictionary <string, string> inputs, IIdentifyLogWriter logWriter)
        {
            var validationResult = ValidateInput(inputs);

            if (validationResult.ResultCode != CredentialsValidationResultCode.Success)
            {
                logWriter.WriteError("Validate the input failed. Error code: " + validationResult.ResultCode +
                                     ". ExternalErrorMessages: " + string.Join("\n-", validationResult.ExternalErrorMessages));
                validationResult.ShowErrorViewWhenResultCodeIsNotSuccess = false;
                return(validationResult);
            }

            var username          = inputs[UserName];
            var password          = inputs[Password];
            var serviceIdentifier = inputs[ServiceIdentifier];

            if (!VerifyIfUserNameIsCorrect(username, logWriter))
            {
                return(new CredentialsValidationResult {
                    ResultCode = CredentialsValidationResultCode.UnknownUserName
                });
            }

            if (!VerifyPasswordIsCorrect(password, logWriter))
            {
                return(new CredentialsValidationResult {
                    ResultCode = CredentialsValidationResultCode.IncorrectPassword
                });
            }

            var logResult = new StringBuilder();

            logResult.AppendLine(
                $"Successfully validate generic credentials for username = '******' with service identifier ='{serviceIdentifier}'");
            logResult.AppendLine("");
            // For this example, we are returning only claims whose types start with "additionalClaims". In reality, here is where you put on your business logic code to return claims.
            var identity = new ClaimsIdentity(AuthenticationTypes.Password);

            foreach (var input in inputs)
            {
                if (input.Key.StartsWith(AdditionalClaims, StringComparison.InvariantCultureIgnoreCase))
                {
                    identity.AddClaim(new Claim(input.Key, input.Value));
                    logResult.AppendLine($"Additional claims received: type = '{input.Key}' - value ='{input.Value}'");
                    if (input.Value.Equals("exception"))
                    {
                        throw new GenericProviderSampleException("Generic provider exception is thrown on UsernamePasswordGenericCredentialsValidator as requested");
                    }
                }
            }
            logWriter.WriteInformation(logResult);

            return(new CredentialsValidationResult {
                ResultCode = CredentialsValidationResultCode.Success, ClaimsPrincipal = new ClaimsPrincipal(identity)
            });
        }
Ejemplo n.º 5
0
        public ClaimsPrincipal Transform(ClaimsPrincipal principal, IDictionary <string, string> inputs, IExternalClaimTransformationPipelineContext pipelineContext)
        {
            if (principal == null)
            {
                throw new ArgumentNullException("principal");
            }

            try
            {
                var type = GetType();
                // each identity provider may add its own identity to the claims principal object
                // at the time the principal object is passed to this transformation rule, how many identities it contains depends on
                // what previous transformations it has gone through.
                // Normally speaking:
                // 1. After Identify receives a token from an upstream Idp or from the UserNamePassword login, it creates the principal with one identity.
                // 2. After that, Identify loads claims from the local store into another identity and adds it to the principal (2 identities so far)
                // 3. There is a setting called "Execute before loading claims from local store" in the claims transformation configuration page which controls
                // if a transformation should be executed before or after the second identity is added.
                // 4. Note 1: Other transformations may add more identities to the claims principal.
                // 5. Note 2: One can choose to add claims to one identity or to all identities depending on specific need.
                foreach (var identity in principal.Identities)
                {
                    identity.AddClaim(new Claim(type.FullName, type.AssemblyQualifiedName));
                    identifyLogWriter.WriteInformation(string.Format(CultureInfo.InvariantCulture,
                                                                     "A new claim is added: [{0},{1}]", type.FullName,
                                                                     type.AssemblyQualifiedName));
                }

                AddConnectionEntityIdentifiers(principal);
            }
            catch (InvalidOperationException ex)   // this exception type is caught for illustration purpose only
            {
                // Ids from 4830 to 4899 are reserved for external components. Pick one that doesn't conflict with other external events in the same set up
                identifyLogWriter.WriteError(4830, ex);
            }

            return(principal);
        }
        public IEnumerable <UserProfile> GetUserProfiles(ControllerContext cc, ClaimsPrincipal principal, IDictionary <string, string> input, string contextId)
        {
            #region sanity checks
            if (cc == null)
            {
                throw new ArgumentNullException("cc");
            }
            if (principal == null)
            {
                throw new ArgumentNullException("principal");
            }
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (contextId == null)
            {
                throw new ArgumentNullException("contextId");
            }
            #endregion

            if (!input.ContainsKey("identityAttributeName"))
            {
                // can write event with id to event log.
                logWriter.WriteError(9999, "The input key-value dictionary doesn't contain identity attribute name. That attribute name is needed to do a look up against a Ldap store");
                throw new ArgumentException(
                          "The input key-value dictionary doesn't contain identity attribute name. That attribute name is needed to do a look up against a Ldap store");
            }
            if (!input.ContainsKey("ldapwsServerName"))
            {
                throw new ArgumentException(
                          "The input key-value dictionary doesn't contain a ldapWS server name (whose key is ldapwsServerName). That ldapWS server name is needed to do a look up against a Ldap store");
            }

            string identityAttributeName = input["identityAttributeName"];
            string ldapwsServerName      = input["ldapwsServerName"];
            // we need to know what user's attribute value should be used to compare against the identityattribute in Ldap
            // default value
            string identityValue = principal.Identity.Name;
            // check if another claim is specified whose value to be used to look up in Ldap
            if (input.ContainsKey("identityClaimType"))
            {
                Claim identityClaim = principal.Claims.FirstOrDefault(claim => claim.Type == input["identityClaimType"]);
                if (identityClaim != null)
                {
                    identityValue = identityClaim.Value;
                }
            }

            // here we assume that attributes to fetch have keys which start with ldapattr_
            var additionalAttributes = input.Where(kvp => kvp.Key.StartsWith("ldapattr_")).Select(kvp => kvp.Value);

            IEnumerable <IDictionary <string, object> > users = identifyLdapStore.GetUsers(identityAttributeName,
                                                                                           identityValue,
                                                                                           ldapwsServerName,
                                                                                           additionalAttributes);
            List <UserProfile> userProfiles = new List <UserProfile>();
            foreach (var user in users)
            {
                // how to map a user object to a user profile depends on specific scenarios.
                // An easy way is to make hard-mapping between a ldap attribute and a userProfile like in this example
                // A more flexible way is to pass such a mapping to this method via the input parameter. The mapping is configured via a UI in Identify*Admin
                // For example:
                //      {prop_identity, samAccountName}
                //      {prop_email, mail}
                //      {prop_photourl, url}

                var userProfile = new UserProfile();
                userProfile.Identity = user["sAMAccountName"].ToString();
                const string displayNameAttr = "Display-Name";
                if (user.ContainsKey(displayNameAttr) && user[displayNameAttr] != null)
                {
                    userProfile.DisplayName = user[displayNameAttr].ToString();
                }
                const string mailAttr = "mail";
                if (user.ContainsKey(mailAttr) && user[mailAttr] != null)
                {
                    userProfile.Email = user[mailAttr].ToString();
                }
                const string photoUrlAttr = "url";
                if (user.ContainsKey(photoUrlAttr) && user[photoUrlAttr] != null)
                {
                    userProfile.PhotoUrl = user[photoUrlAttr].ToString();
                }

                userProfile.Attributes = user;  // finally, assign the "user" object to the Attributes property just in case the caller needs it

                userProfiles.Add(userProfile);
            }

            return(userProfiles);
        }
Ejemplo n.º 7
0
        public CredentialsValidationResult Validate(ControllerContext cc, IDictionary <string, string> input, IIdentifyLogWriter logWriter)
        {
            var validationResult = ValidateInput(input);

            LookupProtocolConnection(cc, logWriter);

            if (validationResult.ResultCode != CredentialsValidationResultCode.Success)
            {
                logWriter.WriteWarning("Validate the input failed. Error code: " + validationResult.ResultCode +
                                       ". ExternalErrorMessages: " + string.Join("\n-", validationResult.ExternalErrorMessages));
                validationResult.ShowErrorViewWhenResultCodeIsNotSuccess = true;
                return(validationResult);
            }

            var connectionString = input[ConnectionString];

            try
            {
                var userRepository = new DummyUserRepository(connectionString);
                var username       = input[UserName].Trim();
                var user           = userRepository.GetUserByName(username);
                if (user == null)
                {
                    logWriter.WriteInformation("User not found. Search username: "******"User information: [UserName: {0}], [Password: {1}], [IsDisabled: {2}], [IsLocked: {3}]",
                                                             user.Username,
                                                             user.Password, user.IsDisabled, user.IsLocked));
                    var password = input[Password].Trim();
                    if (user.Password.Trim() != password)
                    {
                        validationResult.ExternalErrorMessages.Add("Password is invalid. Expected: " + user.Password);
                        validationResult.ResultCode = CredentialsValidationResultCode.IncorrectPassword;
                    }
                    else if (user.IsDisabled)
                    {
                        validationResult.ResultCode = CredentialsValidationResultCode.UserDisabled;
                    }
                    else if (user.IsLocked)
                    {
                        validationResult.ResultCode = CredentialsValidationResultCode.UserLocked;
                    }
                    else
                    {
                        validationResult.UserIdentity = user.Username;
                        validationResult.ResultCode   = CredentialsValidationResultCode.Success;
                    }
                }
            }
            catch (Exception ex)
            {
                logWriter.WriteError("An unexpected exception happends. Error message: " + ex.Message + ". StackTrace: " + ex.StackTrace);

                validationResult.ResultCode = CredentialsValidationResultCode.UnknownError;
                validationResult.ExternalErrorMessages.Add(ex.Message);
            }

            logWriter.WriteInformation("Validation with result code: " + validationResult.ResultCode + ". ExternalErrorMessages: " +
                                       string.Join("\n-", validationResult.ExternalErrorMessages));

            validationResult.ShowErrorViewWhenResultCodeIsNotSuccess = true;
            return(validationResult);
        }
Ejemplo n.º 8
0
        public IEnumerable <UserProfile> GetUserProfiles(ControllerContext cc, ClaimsPrincipal principal, IDictionary <string, string> input, string contextId)
        {
            #region sanity checks
            if (cc == null)
            {
                throw new ArgumentNullException("cc");
            }
            if (principal == null)
            {
                throw new ArgumentNullException("principal");
            }
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (contextId == null)
            {
                throw new ArgumentNullException("contextId");
            }
            #endregion

            if (!input.ContainsKey("identityLocalClaimType"))
            {
                const string errorMessage =
                    "The input key-value dictionary doesn't contain identity claim name. That attribute name is needed to do a look up against a local user store";
                // can write event with id to event log.
                logWriter.WriteError(9999, errorMessage);
                throw new ArgumentException(errorMessage);
            }
            string identityAttributeName = input["identityLocalClaimType"];

            // we need to know what user's claim value should be used to compare against the claim type in local store
            // default value
            string identityValue = principal.Identity.Name;
            // check if another claim is specified whose value to be used to look up in Ldap
            if (input.ContainsKey("identityClaimType"))
            {
                Claim identityClaim = principal.Claims.FirstOrDefault(claim => claim.Type == input["identityClaimType"]);
                if (identityClaim != null)
                {
                    identityValue = identityClaim.Value;
                }
            }

            IEnumerable <IDictionary <string, object> > users = identifyLocalStore.GetUsers(identityAttributeName, identityValue);
            List <UserProfile> userProfiles = new List <UserProfile>();
            foreach (var user in users)
            {
                // how to map a user object to a user profile depends on specific scenarios.
                // An easy way is to make hard-mapping between a claim and a userProfile like in this example
                // A more flexible way is to pass such a mapping to this method via the input parameter. The mapping is configured via a UI in Identify*Admin
                // For example:
                //      {prop_identity, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name}
                //      {prop_email, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress }
                //      {prop_photourl, urn:safewhere:photo:url}

                var userProfile = new UserProfile();
                // This sample assumes that the real username is stored with the claim type below
                userProfile.Identity = ((List <string>)user["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"]).First();

                // __IdentifyUserName is a reserved key for Identify's user name (aka display name)
                // The other two are __Organization and __Group
                const string displayNameAttr = "__IdentifyUserName";
                if (user.ContainsKey(displayNameAttr) && user[displayNameAttr] != null)
                {
                    userProfile.DisplayName = user[displayNameAttr].ToString();
                }

                // This sample assumes that the real email is stored with the claim type below
                const string mailAttr = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
                if (user.ContainsKey(mailAttr) && user[mailAttr] != null)
                {
                    userProfile.Email = GetClaimValue(user[mailAttr]);
                }
                const string photoUrlAttr = "urn:photourl";
                if (user.ContainsKey(photoUrlAttr) && user[photoUrlAttr] != null)
                {
                    userProfile.PhotoUrl = GetClaimValue(user[photoUrlAttr].ToString());
                }

                userProfile.Attributes = user;  // finally, assign the "user" object to the Attributes property just in case the caller needs it

                userProfiles.Add(userProfile);
            }

            return(userProfiles);
        }