DDD Authentication Service

I follow an example in professional ASP.NET design patterns by Scott Millet. In a case study, authentication is performed in the Infrastructure project. It contains implementations such as AspFormsAuthentication: IFormsAuthentication, AspMembershipAuthentication: ILocalAuthenticationService.

This works great because it uses the built-in membership provider, however I am NOT, so I need access to my repositories. In my scenario, would it be better to place my implementation of ILocalAuthenticationService and AspMembershipAuthentication in a Services project?

I asked about this elsewhere, and someone answered:

I would still put functions for transferring credentials at the infrastructure level, since this level is aligned vertically with other horizontal layers, and all layers have access to it. Since you are not using an ASP.NET membership provider, and you can use something user-specific that can simply use encrypted credentials, you can still use the infrastructure layer to wrap access to these credentials and let the repository use them when necessary. You may have a layer of services that will receive them and pass them, but then you have too many levels that understand how the data will be extracted / stored and what access to authorization is required, which is bad when trying to add and separate problems.

Great. It makes sense. But I don’t know where to go from here. Case Study Code:

public class AspMembershipAuthentication : ILocalAuthenticationService 
{
    public User Login(string email, string password)
    {
        User user = new User();
        user.IsAuthenticated= false;

        if (Membership.ValidateUser(email, password))
        {
            MembershipUser validatedUser = Membership.GetUser(email);
            user.AuthenticationToken = validatedUser.ProviderUserKey.ToString();
            user.Email = email;
            user.IsAuthenticated = true;
        }

        return user;
    }

    public User RegisterUser(string email, string password)
    {            
        MembershipCreateStatus status;
        User user = new User();
        user.IsAuthenticated = false;

        Membership.CreateUser(email, password, email, 
                              Guid.NewGuid().ToString(), Guid.NewGuid().ToString(),
                              true, out status);

        if (status == MembershipCreateStatus.Success)
        {
            MembershipUser newlyCreatedUser = Membership.GetUser(email);
            user.AuthenticationToken = newlyCreatedUser.ProviderUserKey.ToString();
            user.Email = email;
            user.IsAuthenticated = true;
        }
        else
        {
            switch (status)
            {
                case MembershipCreateStatus.DuplicateEmail:
                    throw new InvalidOperationException(
                           "There is already a user with this email address.");
                case MembershipCreateStatus.DuplicateUserName:
                    throw new InvalidOperationException(
                           "There is already a user with this email address.");
                case MembershipCreateStatus.InvalidEmail:
                    throw new InvalidOperationException(
                           "Your email address is invalid");
                default:
                    throw new InvalidOperationException(
                    "There was a problem creating your account. Please try again.");
            }
        }

        return user;
    }       
}

If I am not using a membership provider, how do I connect to the database to check if the username and password match, among other possible checks?

+5
source share
1 answer

In your infrastructure layer, create a class that implements ILocalAuthenticationService and makes the calls you need.

Or, if ILocalAuthenticationService is too ASP.NET-y (with its custom return types), you may have to flip your own ILocalAuthenticationService variant and implement it.

IoC ILocalAuthenticationService, .

+3

All Articles