+1-888-365-2779
Try Now
More in this section

Forums / Bugs & Issues / Custom Authentication

Custom Authentication

9 posts, 0 answered
  1. Lucas
    Lucas avatar
    5 posts
    Registered:
    31 Oct 2014
    04 Dec 2014
    Link to this post

    I'm having an issue trying to implement a custom MembershipDataProvider.

    I followed this tutorial and everything seems to work OK. My code runs without error, but after a succesful login I get the following error:

    Exception information:
        Exception type: ArgumentNullException
        Exception message: Value cannot be null.
    Parameter name: value
       at Microsoft.IdentityModel.Claims.Claim..ctor(String claimType, String value, String valueType, String issuer, String originalIssuer)
       at Microsoft.IdentityModel.Claims.Claim..ctor(String claimType, String value, String valueType, String issuer)
       at Microsoft.IdentityModel.Claims.Claim..ctor(String claimType, String value)
       at Telerik.Sitefinity.Security.SitefinityIdentity..ctor(User user, Boolean newLoginDate)
       at Telerik.Sitefinity.Security.Claims.SecurityTokenServiceHttpHandler.SendSimpleWebToken(HttpContextBase context, User user, RequestMessage reqMessage)
       at Telerik.Sitefinity.Security.Claims.SecurityTokenServiceHttpHandler.SendToken(HttpContextBase context, User user, RequestMessage reqMessage, String format)
       at Telerik.Sitefinity.Security.Claims.SecurityTokenServiceHttpHandler.ProcessRequest(HttpContextBase context)
       at Telerik.Sitefinity.Security.Claims.SecurityTokenServiceHttpHandler.ProcessRequest(HttpContext context)
       at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
       at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean & completedSynchronously)

    When I use the default provider everything work ok.

    I'm manually creating the user object and I don't know if thats the proper way of doing it.

    Any idea?

  2. Svetoslav Manchev
    Svetoslav Manchev avatar
    735 posts
    Registered:
    29 Nov 2016
    09 Dec 2014
    Link to this post
    Hello Lucas,

    I have test the code from the tutorial using the full code sample of the custom provider and it seems works fine.

    Would you please elaborate a little more about "manually creating the user" - how the user is created, through the backend UI or through code?

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  3. Lucas
    Lucas avatar
    5 posts
    Registered:
    31 Oct 2014
    09 Dec 2014 in reply to Svetoslav Manchev
    Link to this post

    Thanks for your help Svetoslav.

    I partially managed to solve the problem yesterday. It was an error on my part.

    I'm modifying the sample to work with a web service instead of a database. So I made a mistake Generating the user object.

    But my problems are not over... :(

    Once I succesfully logged a user in the site, this error appears

    "There is no configuration for data provider with the name of "WebApiMembershipProvider" for "Telerik.Sitefinity.Security.UserManager" manager. Please check the spelling of the name and whether such configuration exists. "

    And now I can't even go to the login page. Every time I try it this error appears (While loading the login page).

    What am I missing?

     

     

  4. Svetoslav Manchev
    Svetoslav Manchev avatar
    735 posts
    Registered:
    29 Nov 2016
    12 Dec 2014
    Link to this post
    Hi Lucas,

    Please check once again all the steps in the tutorial and take a special attention of its registration described here.

    In case the issue still persists, would you please attache your code here or open a support ticket and to upload it there in order to inspect it in details.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  5. Lucas
    Lucas avatar
    5 posts
    Registered:
    31 Oct 2014
    16 Dec 2014 in reply to Svetoslav Manchev
    Link to this post

    Well, I checked all the configuration  and the error persists.

    I'm attaching the error page and the code from my provider class. If anyone gets any idea...

    And just to be clear:

    1. I go to the login page
    2. I select my provider
    3. write my user and password
    4. the methods "GetUser" and "ValidateUser" are called and executed whitout error.
    5. then the error page appears
    6. If I stop the Project and run it again, this time the login page doesn't appear, just the same error as before

    Regards

    using System;
    using System.Collections.Generic;
    using System.Configuration.Provider;
    using System.Linq;
    using System.Web.Security;
    using Telerik.Newtonsoft.Json;
    using Telerik.Newtonsoft.Json.Linq;
    using Telerik.Sitefinity.Data;
    using Telerik.Sitefinity.Model;
    using Telerik.Sitefinity.Security;
    using Telerik.Sitefinity.Security.Data;
    using Telerik.Sitefinity.Security.Model;
    using WebAgent.FrontEndSite.Helpers;
     
    namespace WebAgent.FrontEndSite.Providers
    {
        public class WebApiMembershipProvider : MembershipDataProvider
        {
            private readonly ManagerInfo _managerInfo;
     
            public WebApiMembershipProvider()
                : base()
            {
                ProviderName = "WebApiMembershipProvider";
                _managerInfo = new ManagerInfo
                {
                    ProviderName = ProviderName,
                    ManagerType = "Telerik.Sitefinity.Security.UserManager",
                    ApplicationName = "/WebApiMembershipProvider"
                };
            }
     
            #region Properties
            public string ProviderName { get; set; }
            public override string ApplicationName { get { return ManagerInfo.ApplicationName; } }
            private ManagerInfo ManagerInfo { get { return _managerInfo; } }
     
            public override ProviderAbilities Abilities
            {
                get
                {
                    var abilities = new ProviderAbilities { ProviderName = Name, ProviderType = GetType().FullName };
                    abilities.AddAbility("GetUser", true, true);
                    abilities.AddAbility("CreateUser", true, true);
                    abilities.AddAbility("DeleteUser", true, true);
                    abilities.AddAbility("UpdateUser", true, true);
                    abilities.AddAbility("ValidateUser", true, true);
                    abilities.AddAbility("ResetPassword", true, true);
                    abilities.AddAbility("GetPassword", false, false);
                    return abilities;
                }
            }
            #endregion
     
            #region Methods
            protected override object CreateNewTransaction(string transactionName)
            {
                return new object();
            }
     
            public override void CommitTransaction() { }
     
            protected override void Dispose(bool disposing)
            {
                if (!disposing)
                    base.Dispose(false);
            }
     
            public override bool EmailExists(string email)
            {
                var parameters = new Dictionary<string, string> { { "mail", email } };
                var result = ServiceClient.Get("api/Security/MailExists", parameters);
                return result == "true";
            }
     
            public override bool UserExists(string userName)
            {
                var parameters = new Dictionary<string, string> { { "username", userName } };
                var result = ServiceClient.Get("api/Security/UsernameExists", parameters);
                return result == "true";
            }
     
            private User GetSitefinityUser(JObject jsonUser)
            {
                var user = new User
                {
                    ApplicationName = ApplicationName,
                    IsBackendUser = jsonUser["field_IsBackendUser"].Value<bool>(),
                    Id = new Guid(jsonUser["field_Id"].Value<string>()),
                    Email = jsonUser["field_Mail"].Value<string>(),
                    Comment = jsonUser["field_Comment"].Value<string>(),
                    LastActivityDate = DateTime.UtcNow.AddDays(-1),
                    LastModified = DateTime.MinValue,
                    LastLoginDate = DateTime.MinValue,
                    FailedPasswordAnswerAttemptWindowStart = DateTime.MinValue,
                    FailedPasswordAttemptWindowStart = DateTime.MinValue,
                    Password = jsonUser["field_Password"].Value<string>() + jsonUser["field_Salt"].Value<string>(),
                    Salt = jsonUser["field_Salt"].Value<string>(),
                    ManagerInfo = ManagerInfo,
                    IsApproved = jsonUser["field_IsApproved"].Value<bool>(),
                    //PasswordFormat = 2
                };
                user.SetUserName(jsonUser["field_UserName"].Value<string>());
                user.SetCreationDate(DateTime.Now);
                user.SetIsLockedOut(jsonUser["field_IsLockedOut"].Value<bool>());
                user.SetLastLockoutDate(DateTime.Now);
                user.SetLastPasswordChangedDate(DateTime.Now);
                user.SetPasswordQuestion(jsonUser["field_Question"].Value<string>());
                return user;
            }
     
            public override IQueryable<User> GetUsers()
            {
                throw new NotSupportedException();
            }
     
            public override User GetUser(Guid id)
            {
                var parameters = new Dictionary<string, string> { { "id", id.ToString() } };
                var result = ServiceClient.Get("api/Security/GetUserById", parameters);
                var user = JsonConvert.DeserializeObject<JObject>(result);
                return GetSitefinityUser(user);
            }
     
            public override User GetUserByEmail(string email)
            {
                var parameters = new Dictionary<string, string> { { "mail", email } };
                var result = ServiceClient.Get("api/Security/GetUserByMail", parameters);
                var user = JsonConvert.DeserializeObject<JObject>(result);
                return GetSitefinityUser(user);
            }
     
            public override User GetUser(string userName)
            {
                var parameters = new Dictionary<string, string> { { "username", userName } };
                var result = ServiceClient.Get("api/Security/GetUserByLogin", parameters);
                var user = JsonConvert.DeserializeObject<JObject>(result);
                return GetSitefinityUser(user);
            }
     
            public override User CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
            {
                // First we validate the given parameters
                if (!ValidateParameters(ref username, ref password, ref email, ref passwordQuestion, ref passwordAnswer, ref providerUserKey, out status))
                    return null;
     
                // Generate a new Salt
                var str = GenerateSalt();
                // Get a UTC DateTime
                var utcNow = DateTime.UtcNow;
                // Create a new user with the parameters entered from the Sitefinity backend
                var newUser = CreateUser((Guid)providerUserKey, username);
                newUser.Password = EncodePassword(password, str, PasswordFormat);
                newUser.PasswordAnswer = EncodePassword(passwordAnswer.ToUpperInvariant(), null, PasswordFormat);
                newUser.Salt = str;
                newUser.Email = email;
                newUser.Comment = string.Empty;
                newUser.IsApproved = isApproved;
                newUser.FailedPasswordAttemptCount = 0;
                newUser.FailedPasswordAttemptWindowStart = utcNow;
                newUser.FailedPasswordAnswerAttemptCount = 0;
                newUser.FailedPasswordAnswerAttemptWindowStart = utcNow;
                newUser.PasswordFormat = (int)PasswordFormat;
                newUser.PasswordAnswer = passwordAnswer;
                newUser.SetPasswordQuestion(passwordQuestion);
                newUser.SetCreationDate(DateTime.Now);
     
                // Add the new user to the Switch in our custom database
                var user = new JObject {
                    {"username",username},
                    {"firstname",""},
                    {"lastname",""},
                    {"password",password},
                    {"email",email}
                };
                ServiceClient.Post("api/NewUser", user);
     
                // Return our new Sitefinity User
                return newUser;
            }
     
            public override User CreateUser(string userName)
            {
                return CreateUser(GetNewGuid(), userName);
            }
     
            public override User CreateUser(Guid id, string userName)
            {
                if (id == Guid.Empty) throw new ArgumentNullException("id");
                if (!string.IsNullOrEmpty(userName))
                {
                    LoginUtils.CheckParameter(userName, true, true, true, 256, "userName");
                    if (UserExists(userName))
                        throw new ProviderException("Username already exists.");
                }
     
                var user = new User { ApplicationName = ApplicationName, Id = id };
                user.SetUserName(userName);
                ((IDataItem)user).Provider = this;
                user.ManagerInfo = ManagerInfo;
                return user;
            }
     
            public override bool ValidateUser(string userName, string password)
            {
                return ValidateUser(GetUser(userName), password);
            }
     
            public override bool ValidateUser(User user, string password)
            {
     
                if (user == null) return false;
                var flag = CheckValidPassword(user, password);
                if (flag)
                {
                    user.LastLoginDate = DateTime.UtcNow;
                    user.FailedPasswordAttemptWindowStart = DateTime.UtcNow;
                    user.FailedPasswordAttemptCount = 0;
                }
                else
                    UpdateFailureCount(user, "password");
                return flag;
            }
     
            private bool CheckValidPassword(User user, string password)
            {
                var parameters = new Dictionary<string, string>
                {
                    {"grant_type","password"},
                    {"username",user.UserName},
                    {"password",password}
                };
                try
                {
                    var token = ServiceClient.Post("Token", parameters).Length > 0;
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
             
            public override void Delete(User item)
            {
                throw new NotSupportedException();
            }
     
            public override string GetPassword(User user, string answer)
            {
                throw new NotSupportedException();
            }
     
            public override string GetPassword(string userName, string answer)
            {
                throw new NotSupportedException();
            }
     
            public override string GetPassword(Guid userId, string answer)
            {
                return GetPassword(GetUser(userId), answer);
            }
     
            public override string ResetPassword(User user, string answer)
            {
                throw new NotSupportedException();
            }
     
            public override string ResetPassword(string userName, string answer)
            {
                throw new NotSupportedException();
            }
     
            public override string ResetPassword(Guid userId, string answer)
            {
                throw new NotSupportedException();
            }
     
            #endregion
     
            #region Not Supported
     
            public override bool ChangePassword(Guid userId, string oldPassword, string newPassword)
            {
                throw new NotSupportedException();
            }
     
            public override bool ChangePassword(string userName, string oldPassword, string newPassword)
            {
                throw new NotSupportedException();
            }
     
            public override bool ChangePassword(User user, string oldPassword, string newPassword)
            {
                throw new NotSupportedException();
            }
     
            public override bool ChangePasswordQuestionAndAnswer(User user, string password, string newPasswordQuestion, string newPasswordAnswer)
            {
                throw new NotSupportedException();
            }
     
            public override bool ChangePasswordQuestionAndAnswer(Guid id, string password, string newPasswordQuestion, string newPasswordAnswer)
            {
                throw new NotSupportedException();
            }
     
            public override bool ChangePasswordQuestionAndAnswer(string userName, string password, string newPasswordQuestion, string newPasswordAnswer)
            {
                throw new NotSupportedException();
            }
     
            public override System.Collections.IEnumerable GetItems(Type itemType, string filterExpression, string orderExpression, int skip, int take, ref int? totalCount)
            {
                throw new NotSupportedException();
            }
     
            public override bool UnlockUser(Guid userId)
            {
                throw new NotSupportedException();
            }
     
            public override bool UnlockUser(string userName)
            {
                throw new NotSupportedException();
            }
     
            public override bool UnlockUser(User user)
            {
                throw new NotSupportedException();
            }
            #endregion
     
        }
    }

     

  6. Svetoslav Manchev
    Svetoslav Manchev avatar
    735 posts
    Registered:
    29 Nov 2016
    19 Dec 2014
    Link to this post
    Hello Lucas,

    Would you please check in the SecurityConfig.config (~/App_Data/Sitefinity/Configuration/) is there registration of your custom membership provider with the same name as in the error: WebApiMembershipProvider, in the list of the " <membershipProviders>" providers.

    This settings are in the backend: Administration > Settings > Advanced > Security > Membership Providers > (your provider)

    In the example I have tested the settings are: http://screencast.com/t/cMLamuAB.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  7. Lucas
    Lucas avatar
    5 posts
    Registered:
    31 Oct 2014
    19 Dec 2014 in reply to Svetoslav Manchev
    Link to this post

    I'm attaching a screenshot of the configuration page in the backend and the fragment of the config:

    <membershipProviders>
        <add title="WebApi" description="Web API service" type="WebAgent.FrontEndSite.Providers.WebApiMembershipProvider, WebAgent.FrontEndSite" ApplicationName="/WebApiMembershipProvider" maxInvalidPasswordAttempts="5" enablePasswordReset="True" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="7" newPasswordLength="8" passwordAttemptWindow="10" passwordFormat="Clear" requiresQuestionAndAnswer="False" requiresUniqueEmail="True" enablePasswordRetrieval="False" enabled="True" name="WebApi" />
    </membershipProviders>

  8. Svetoslav Manchev
    Svetoslav Manchev avatar
    735 posts
    Registered:
    29 Nov 2016
    24 Dec 2014
    Link to this post
    Hi Lucas,

    Please try to change the name of the provide as in the provide type (WebApiMembershipProvider) and restart the application.

    Regards,
    Svetoslav Manchev
    Telerik
     
    Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
  9. Lucas
    Lucas avatar
    5 posts
    Registered:
    31 Oct 2014
    29 Dec 2014
    Link to this post
    Yup. That Works.
    In the provider tag, the "name" attribute must be the same as the class name. I changed that and solved the problem.
    Thanks!
9 posts, 0 answered