Showing posts with label Authentication. Show all posts
Showing posts with label Authentication. Show all posts

Thursday, July 23, 2015

Security Auditing in WCF

It is possible to log all security successes and/or failures to the event log by just modifying your configuration file.  This can be a quick and easy way to see if any funny business is going on with your web service.  However, a better solution is to log these types of events to a database that is easier to check and query on if you're doing this on a regular basis.

I'm a fan of the Service Configuration Editor tool (In Visual Studio, right click the web.config and select Edit WCF Configuration) rather than changing the XML directly, but it's helpful to see both.

First add a Service Behavior Configuration.  It doesn't necessarily have to be named.  Then add the serviceSecurityAudit behavior to the configuration:


Now, expand the behavior configuration, and select the newly added serviceSecurityAudit:


I recommend choosing the "Application" log as the location.  Here, I have chosen to log both successes and failures at the message level.  Once this is set up, simply go to the Event Viewer and you'll see information entries for each authentication or rejection.  To turn it off, just set it to None and leave it in the web.config in case you want to turn it on again.

Here is the settings as they exist in the XML:

<behaviors>
  <servicebehaviors>
    <behavior name="">

...

      <servicesecurityaudit auditloglocation="Application" 
          messageauthenticationauditlevel="SuccessOrFailure" 
          serviceauthorizationauditlevel="None">
      </servicesecurityaudit>
    </behavior>
  </servicebehaviors>
</behaviors>

Thursday, September 4, 2014

Use SoapUI to test your web services

Recently, I created a web service that external organizations would use as an API to access our data.  I decided to use WCF and the SOAP architecture to achieve this.  I also created a little .NET console app to test the web service.  Everything worked great.  However, I was a little concerned that I might have unintentionally wrote some code that was only supported by the Microsoft stack.  How could I be sure that my web service could be used by someone using a different platform?

My first idea was to try to access the web service using jQuery.  I felt that if I could successfully invoke the web service using jQuery or JavaScript, this would demonstrate that Microsoft technology wasn't necessary to use my service.  However, I found that calling a SOAP based web service from client side scripting is not an easy task.  In fact, I never got this to work, and there is not a lot of information out there about how to do this.  One problem is that browsers have security measures to stop cross site scripting.  So the web service has to be part of the same site.  If you can get past that, you also have to manually build the SOAP envelope in your javascript which is tedious.  On top of that you have to figure out how to specify your logon credentials within the request.  I concluded that it is just not practical to call a SOAP service from the client.  I think this is where the advantages of using a REST style web service really pay off.

I discovered a widely used application called SoapUI.  It is a free download, and you can use it to invoke the methods of your web service for testing purposes.  This is a way to independently test your web service operations without being bound to Microsoft.

Installation is straight forward and instructions can be found on the site.  Note that you do not need to install Hermes if you're not testing a Java service.

Here is how to test a web service operation.

  1. Open SoapUI and right click on Projects, New SOAP Project.
  2. Name the project and specify the address of the WSDL of your service.
  3. Check the box that says Create Sample Requests.
  4. In the navigator, you'll see each operation of the service.  If you click the plus sign next to each operation you will see the sample request that was created for you.
  5. Click on the request and find the request properties.
  6. If the web service security is set up for TransportWithMessageCredential, then set the username and password properties to something that works.  Also set the WSS-Password Type to PasswordText.
  7. Double-click the request.
  8. In the request window, you'll see the SOAP envelope.  You can see where the parameters go, and can set these here.
  9. Then, click the green arrow which sends the request to the web service.
  10. The results will be shown in the right-hand pane.

Thursday, June 12, 2014

Recaptcha

If your project requires CAPTCHA functionality, I highly recommend Recaptcha.  Recaptcha is a free service offered by Google that serves up CAPTCHA functionality.  First, you need to sign up here.  Assuming you've got a google id and are signed in, all you need to provide is the domain where you will be using recaptcha.  Google will provide you a public and private key that will be used by the recaptcha control.

For ASP.NET, you just need to download the recaptcha dll and reference it in your project.  Then put this at the top of the page where the CAPTCHA functionality is needed:

<%@ Register TagPrefix="recaptcha" Namespace="Recaptcha" Assembly="Recaptcha" %>

This snippet will render the CAPTCHA control itself:

                    <recaptcha:RecaptchaControl
                        ID="recaptcha"
                        runat="server"
                        Theme="white"
                        PublicKey="Provided By Google"
                        PrivateKey="Provided By Google"
                    />


And finally, this code will check to make sure the correct code was entered. This assumes you have a ValidationSummary control on your page.

        If Page.IsValid = False Then
            Return
        End If

Friday, March 21, 2014

ASP.NET Identity - Get a user id

After a user logs in, how do you get the user id, which is stored as a GUID?  You don't have to go through the UserManager class which would require a trip to the database.  You can use the following code but you have to include the Imports statement or it won't work.

Imports Microsoft.AspNet.Identity

...

User.Identity.GetUserId()

Thursday, March 20, 2014

ASP.NET Identity - Using Roles

Roles allow you to restrict parts of your application to specific roles.  These roles are stored in the AspNetRoles table that is created by ASP.NET Identity.  You can create roles programatically or just insert them directly into the table using SQL.  If you're using SQL, you can just use an INSERT statement with a GUID and a name.  Programmatically, you would do the following:

Dim MyRoleStore As New RoleStore(Of IdentityRole)
Dim MyRoleManager As New RoleManager(Of IdentityRole)(MyRoleStore)

MyRoleManager.Create(New IdentityRole("Support Staff"))

IdentityRole is the Entity Framework object that ultimately represents (mapped to) a row in the AspNetRoles table.

Once you have some roles defined, you can associate a role to a user like this:

Dim Result As IdentityResult = _
     Await UserManager.AddToRoleAsync(MyUser.Id, "Support Staff")

Finally in order to restrict parts of your application, you simple add an Authorize filter to the ActionMethod you want restricted like this:

<Authorize(Roles:="Support Staff")>
Function MyActionMethod() As ActionResult

    ...

    Return View()

End Function

Finally, if the user is not authorized, they will be redirected to a specific page, usually the login page.  ASP.NET Identity is not forms authentication so this redirect is not in the web.config.  In an MVC app, it is in the Startup.Auth class ConfigureAuth method:

app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.LoginPath = New PathString("/Account/Login")})

Tuesday, March 18, 2014

ASP.NET Identity Basics

ASP.NET Identity is a system for handling authentication and authorization.  It was released with .NET 4.5.1 that shipped with Visual Studio 2013.  It replaces ASP.NET Membership.

Like Membership, it is a (sort of) simple way to implement forms authentication in a .NET application.  Identity differs from Membership in that it can be unit tested, allows external providers (such as Facebook and Google), and it works for all .NET technologies.

It is surprisingly easy to configure a new MVC web application for forms authentication using Identity.  Simply add an ASP.NET Web Application project and choose MVC with Individual User Accounts.  Remember to set the Framework version of the new project to 4.5.1 or you will not have these options.

The resulting project will contain:
  1. An AccountController class that will handle all authentication and user profile functionality.
  2. A web.config with a connection string pointing at a yet-to-be-created LocalDB database.
  3. A set of Account views that handles logging in, registrations, and user profile management.
  4. An AccountViewModels file that contain view models the Account views use.
  5. An IdentityModel file that contain classes that derive from the built in Identity classes.
  6. A Startup.Auth file that contains code to configure authentication on start up.
All of this is nicely integrated with the default views and controllers that the ASP.NET template has included for a standard MVC application.  You can run it and start registering and logging in immediately with no additional configuration.

It is important to understand the users and passwords are stored in the LocalDB database referred to in the web.config file.  This database is created by ASP.NET when you register the first user.  When you want to go to production, you can just script this thing out and move it to a production SQL Server.

If you look at the AccountController code, you'll notice that a Microsoft.AspNet.Identity.UserManager class is called for much of the authentication functionality.  The UserManager class almost exclusively offers asynchronous methods.  Therefore, you have to follow the rules of calling asynchronous methods when using this class.

Thursday, February 27, 2014

Two ways to validate a string against a regular expression

The .NET framework provides at least two ways to accomplish regular expression validation.  Microsoft seems to prefer you use RegExStringValidator for simple validation, but as you can see below, it is anything but simple.  I see no reason not to use the RegEx class which is much cleaner.

Use the RegExStringValidator class


Dim MyRegEx As String = "(?=.{8,})(?=(.*\d){1,})(?=(.*[A-Z]){1,})(?=(.*[a-z]){1,})"

Dim MyRegExValidator As New System.Configuration.RegexStringValidator(MyRegEx)

Try

    Dim StringToValidate As String = "gDLDdE12"

    If MyRegExValidator.CanValidate(StringToValidate.GetType()) Then
        MyRegExValidator.Validate(StringToValidate)
    End If

    'If no exception occurs, then the validation succeeded.
    
Catch ex As Exception

    'If an exception occurs, then the validation failed.

End Try


Use the RegEx class


Dim RegExEngine As System.Text.RegularExpressions.Regex = _
    New System.Text.RegularExpressions.Regex("(?=.{8,})(?=(.*\d){1,})(?=(.*[A-Z]){1,})(?=(.*[a-z]){1,})")

If RegExEngine.IsMatch(NewPassword.Text) Then
    'Validation is successful.
Else
    'Validation is not successful.
End If

Wednesday, February 26, 2014

Regular Expressions for password validation

Regular Expressions can look like Greek and be a real pain to wrap your head around, but sometimes they are necessary.  It's fairly easy to find a regular expression for common uses like email and phone numbers.  However, I didn't have much luck finding a regular expression to validate the format of a password.  This is probably because there are so many variations on what is considered an acceptable password.

By reverse engineering some Microsoft examples, I've discovered an easy way to create a regular expression for your specific password validation needs.

Let's walk through this:

What is the minimum length of the password?  Let's say 8.  So start with:

(?=.{8,})

Do you require at least one number?  If yes, then append:

(?=(.*\d){1,})

Do you require at least one capital letter?  If yes, then append:

(?=(.*[A-Z]){1,})

Do you require at least one lower case letter?  If yes, then append:

(?=(.*[a-z]){1,})

Do you require at least one "special" character?  If yes, then append:

(?=(.*\W){1,})

When we string these requirements together, we get:

(?=.{8,})(?=(.*\d){1,})(?=(.*[A-Z]){1,})(?=(.*[a-z]){1,})(?=(.*\W){1,})

By omitting and including the various sections, you should be able to create a regular expression that matches your application's definition of an "acceptable" password.

Tuesday, January 14, 2014

What is ASP.NET Impersonation?

When using Windows authentication, the User property of the HttpContext will be set to whoever is browsing your web application.  This allows a programmer to do certain things based on the user who is currently accessing the system.  However, the current user will not be used to determine access to file resources or connect to a database for example.  (I believe the application pool identity is used by default).  What if you want to use the current user for this other access?

You need to impersonate the current user when accessing these resources.  Simply put the following in your web.config file:
<system.web>
    <identity impersonate="true" />
</system.web>
You can also specify a username and password to use.  I'm not sure the value in this since you could always just use the app pool identity, but if you need to, do this....
<system.web>
    <identity impersonate="true" userName="Steve" password="Supersecret" />
</system.web>

Tuesday, December 17, 2013

Show or Hide the login window when accessing a site that uses Windows Authentication.

You're working on a site that is set up for Windows Authentication.  Two scenarios:

  1. You want your credentials to "pass through" without logging in.  In IE, open Internet Options, Security tab.  Select the zone the site is in, or add it to a zone if appropriate.  Click the Custom Level button.  Scroll down and select the "Automatic logon with current username and password" under the User Authentication, Logon section.
  2. You don't want to be logged in automatically so you can log in as other people for testing or whatever.  Follow the steps above except choose the "Prompt for username and password" radio button.