Search code examples
c#.netopenidgoogle-openid

C# open ID authentification in prod only


I'm using C# with VS2012 for a small project. The project I work on is a site which requires users to log in via open ID (facebook, google, etc).

After adding authentication to the website I have to log in before testing and trying things out. This is an annoyance and makes no sense for a dev environment.
Is there a way to not have authentication or skip it in dev and add it only when the code it deployed to production?


Solution

  • Yes, there is. However, there is no one shot solution. Depending on how you authenticate the users, the solution may be different. One idea is to use Preprocessor Directives. This way you can conditionally compile the authentication code based on if you are building a debug version or a release version.

    For example, in an MVC app with forms authentication you might use this:

    //Define that we are debugging
    #define DEBUG    
    
    public ActionResult DoSomething()
    {
        //Determine if this is a debug build
        //If it is, then we want to exclude the authentication verification
        //portion of the code
    
        //Include the code if DEBUG has not been defined
        #if !DEBUG
        if(!HttpContext.User.Identity.IsAuthenticated)
        {
           //Not authenticated
           return new HttpUnauthorizedResult();
        }
        #endif
        //Authenticated
        DoOtherStuff();
    }
    

    As you can see, the HttpUnathorizedException is only thrown when the DEBUG directive has not been defined. DoOtherStuff() is always executed even though the user might not be logged in.

    The problem with this approach is the fact that usually when you require the user to be logged in, you need his/her account details to do something.

    For example:

    public ActionResult Post(PostModel post)
    {
        #if !DEBUG
        if(!HttpContext.User.Identity.IsAuthenticated)
        {
            return new HttpUnauthorizedResult();
        }
        #endif
    
        User user = GetLoggedInUser(); //Returns null because the user
                                       //is not authenticated
    
        Post createdPost = new Post
        {
           Title = post.Title,
           Content = post.Content,
    
           //Uh oh, the user is not logged in. This post will not have an author!
           Author = user,
           PostDate = DateTime.Now
        };
    
        DbContext.Posts.Add(createdPost);
        DbContext.SaveChanges();
    
        return View();
    }
    

    A different solution would allow the user to log in without actually logging in.

    For example:

    public ActionResult LogIn(string username)
    {
        #if !DEBUG
           //Require the user to actually login through OpenId
        #else
           //Don't require the user/dev to actually login, instead just give them access
           FormsAuthentication.SetAuthCookie(username, false);
        #endif
    }
    

    Then, when the user/dev tries to access something...

    public ActionResult Post(PostModel post)
    {
        // The user will be logged in because you just gave them the
        // authentication cookie
        if(!HttpContext.User.Identity.IsAuthenticated)
        {
            return new HttpUnauthorizedResponse();
        }
        else
        {
           User user = GetLoggedInUser(); //Returns user
           Post createdPost = new Post
           {
              //ect..
              User = user
           };
    
           // Save post
    
           return View();
        }
    }
    

    Overall to answer your question:

    Is there a way to not have authentication or skip it in dev and add it only when the code it deployed to production?

    Yes, however an exact solution is dependent on your situation.