Introduction
So this week I wanted to setup a webservice that also included authentication. As one usually does this time of the year, Santa needs his data to be protected so that the children can’t see which gifts they will receive.
I decided to help Santa by using ServiceStack and Easyhttp.
ServiceStack
Lets start by creating our server first. For this I make a new Empty ASP.Net project. And I change the web.config to this.
```xml <?xml version=“1.0”?>
<!– For more information on how to configure your ASP.NET application, please visit <a href=“http://go.microsoft.com/fwlink/?LinkId=169433"> http://go.microsoft.com/fwlink/?LinkId=169433</a> –>
<configuration> <system.web> <compilation debug=“true” strict=“false” explicit=“true” targetFramework=“4.0” /> </system.web> <system.web> <httpHandlers> <add path=”” type=“ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack” verb=””/> </httpHandlers> </system.web>
<!– Required for IIS 7.0 –> <system.webServer> <validation validateIntegratedModeConfiguration=“false” /> <handlers> <add path=”” name=“ServiceStack.Factory” type=“ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack” verb=”” preCondition=“integratedMode” resourceType=“Unspecified” allowPathInfo=“true” /> </handlers> </system.webServer> </configuration>``` Then I create Three folders. Request, Response and Service.
The Request Is one Class. With one property. So that the user (Santa and his elf’s) can select if he wants a list of all the Good Boys and Girls or all the bad ones.
vbnet
Namespace Request
Public Class GoodOrBadRequest
Public Property Good As Boolean?
End Class
End Namespace
And the Response will be this.
vbnet
Namespace DefaultNamespace.Response
Public Class Children
Public Property LastName As String
Public Property Good As Boolean?
End Class
End Namespace
And we also need a Service Class.
```vbnet Imports SantaGoodAndBad.Response Imports SantaGoodAndBad.Request Imports ServiceStack.ServiceInterface
Namespace DefaultNamespace.Service Public Class GoodOrBadService Inherits RestServiceBase(Of GoodOrBadRequest)
Public Overrides Function OnGet(request As GoodOrBadRequest) As Object
If request.Good.HasValue Then
Return MakeChildren.Where(Function(child) child.Good.Value = request.Good.Value).ToList
Else
Return MakeChildren()
End If
End Function
Private Function MakeChildren() As IList(Of Child)
Dim children As New List(Of Child)
children.Add(New Child With {.LastName = "Baes", .Good = True})
children.Add(New Child With {.LastName = "Hariri", .Good = False})
children.Add(New Child With {.LastName = "Hanselman", .Good = True})
children.Add(New Child With {.LastName = "Krueger", .Good = False})
Return children
End Function
End Class
End Namespace``` And then it is time to create a new AppHost file.
And now this is where it gets interesting.
```vbnet Imports ServiceStack.CacheAccess.Providers Imports ServiceStack.CacheAccess Imports ServiceStack.ServiceInterface.Auth Imports SantaGoodAndBad.Request Imports SantaGoodAndBad.DefaultNamespace.Service Imports ServiceStack.ServiceInterface Imports ServiceStack.WebHost.Endpoints
Public Class AppHost Inherits AppHostHttpListenerBase
Public Sub New()
MyBase.New("Good or bad", GetType(GoodOrBadService).Assembly)
End Sub
Public Overrides Sub Configure(container As Funq.Container)
Routes.Add(Of GoodOrBadRequest)("/GoodOrBad") _
.Add(Of GoodOrBadRequest)("/GoodOrBad/{Good}")
Plugins.Add(New AuthFeature(Function() New AuthUserSession(), New AuthProvider() {New CredentialsAuthProvider()}))
container.Register(Of ICacheClient)(New MemoryCacheClient())
Dim userRep = New InMemoryAuthRepository()
container.Register(Of IUserAuthRepository)(userRep)
Dim hash As String
Dim salt As String
Dim s = New SaltedHash()
s.GetHashAndSaltString("test", hash, salt)
userRep.CreateUserAuth(New UserAuth With {.Id = 1, .DisplayName = "DisplayName", .Email = "as@if.com", .UserName = "cbaes", .FirstName = "FirstName", .LastName = "LastName", .PasswordHash = hash, .Salt = salt}, "test1")
End Sub
End Class``` As you can see above. I create 2 routes. And then I add the auth plugin. And one user to authenticate against. And that’s it.
Now to change our Global.asax.
```vbnet Imports System.Web.SessionState
Public Class Global_asax Inherits System.Web.HttpApplication
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Dim apphost = New AppHost()
apphost.Init()
End Sub
End Class``` And now we can view the above in a browser.
Now if I go to the GoodOrBad page. I can still see my children.
And that was not the point. So what did I forget.
I forgot to tell ServiceStack which requests to authenticate.
I can do this on the service or on the request object. I will do it on the request object.
```vbnet Imports ServiceStack.ServiceInterface
Namespace Request <Authenticate> Public Class GoodOrBadRequest Public Property Good As Boolean? End Class End Namespace``` And now when I try to go to GoodOrBad I get this.
So I need to login.
You can login by doing this auth?username=cbaes&password=test1
And then you get the following response.
And now you can see your data again.
And to log back out you can use this /auth/logout
Easyhttp
This post was getting to long so I will discuss that in my next post. And in post 3 there is more about roles.
Conclusion
Authentication is very easy to setup in ServiceStack.