Skip to content

Authentication and authorization

joshilewis edited this page Feb 13, 2012 · 95 revisions

Authentication and authorization in ServiceStack

General

ServiceStack supports basic authentication and OAuth authentication out of the box. You can read more about Basic and OAuth authentication at Wikipedia:

The Social Bootstrap API example, specifically the AppHost class, shows ways to configure various authentication options. Another good source for ways to configure Authentication is the AuthTests unit test

The minimum configuration needed to get Basic Authentication up and running is the following in the AppHost.Config() (taken from the AuthTests unit test ) :

        public override void Configure(Container container)
        {
            AuthService.Init(this, () => new AuthUserSession(), new IAuthProvider[]
                {
                    new BasicAuthProvider()
                });

            container.Register<ICacheClient>(new MemoryCacheClient());
            var userRep = new InMemoryAuthRepository();
            container.Register<IUserAuthRepository>(userRep);

            //Add a user for testing purposes
            userRep.CreateUserAuth(new UserAuth
            {
                Id = 1,
                DisplayName = "DisplayName",
                Email = "as@if.com",
                UserName = "user",
                FirstName = "FirstName",
                LastName = "LastName",
                PasswordHash = hash,
                Salt = salt,
            }, "pass");
        }

This gives you Basic Authentication for all DTOs and Services which require authentication (see below for making DTOs and services require authentication). However this code specifies that both the CacheClient and UserAuthRepository used are in-memory. Once you've got this working you'll probably want to use a different implementation of IUserAuthRepository. ServiceStack provides both Redis and OrmLite implementations out the box. You are also free to create your own implementation (just remember to register it in the container). You may also want to provide a different implementation of ICacheClient. Cache Clients are discussed more below.

The classes in ServiceStack have been designed to provide default behaviour out the box (so-called convention over configuration). They are also highly customisable. Both the default BasicAuthProvider and CredentialsAuthProvider (which it extends) can be extended, and their behaviour over-ridden. An example is below:

public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
    public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        //Add here your custom auth logic (database calls etc)
        //Return true if credentials are valid, otherwise false
    }

    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        //Fill the IAuthSession with data which you want to retrieve in the app eg:
        session.FirstName = "some_firstname_from_db"
        //...
            
        //Important: You need to save the session!
        authService.SaveSession(session);
    }
}

Then you need to register your custom credentials auth provider:

    //Register all Authentication methods you want to enable for this web app.
    AuthService.Init(this, () => new AuthUserSession()
        new IAuthProvider[] {
	    new CustomCredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
    });

Afer that you need to register the routes for authentication in your AppHost:

Routes
//Using ServiceStack's built-in Auth and Registration services
    .Add<Auth>("/auth")

POST localhost:60339/auth?provider=credentials?format=json

{
    "UserName": "admin",
    "Password": "test"
    "RememberMe": true
}

When the client now tries to authenticate with the request above and the auth succeeded, the client will retrieve some cookies with a session id which identify the client on each webservice call.

But how does ServiceStack remember which session id belongs to which client?
For this purpose, ServiceStack uses an ICacheClient. A cache client is actually a simple key/value-store. When the cache client is used to save client session, the key is the session id and the value is an instance of the interface IAuthSession.

The IAuthSession can be accessed inside a ServiceStack service:

public class SecuredService : RestServiceBase<Secured>
{
    public override object OnGet(Secured request)
    {
        AuthUserSession session = this.GetSession();
        return new SecuredResponse() { Test = "You're" + session.FirstName };
    }
}

ServiceStack uses the CacheClient which was registered in the IoC container:

//Register a external dependency-free 
container.Register<ICacheClient>(new MemoryCacheClient() { FlushOnDispose = false });
//Configure an alt. distributed peristed cache that survives AppDomain restarts. e.g Redis
//container.Register<IRedisClientsManager>(c => new PooledRedisClientManager("localhost:6379"));

Tip: If you've got multiple server which run the same ServiceStack service, you can use Redis to share the sessions between these servers.


Please look at SocialBootstrapApi to get a full example.

Of course you can also implement your own - custom - authentication mechanism. You aren't forced to use the built-in ServiceStack auth mechanism.

The Authenticate attribute

But how does ServiceStack know, which service needs authentication? This happens with the AuthenticateAttribute.

You simply have to mark your request dto with this attribute:

//Authentication for all HTTP methods (GET, POST...) required
[Authenticate()]
public class Secured
{
    public bool Test { get; set; }
}

Now this service can only be accessed if the client is authenticated:

public class SecuredService : RestServiceBase<Secured>
{
    public override object OnGet(Secured request)
    {
        IOAuthSession session = this.GetSession();
        return new SecuredResponse() { Test = "You're" + session.FirstName };
    }

    public override object OnPut(Secured request)
    {
        return new SecuredResponse() { Test = "Valid!" };
    }

    public override object OnPost(Secured request)
    {
        return new SecuredResponse() { Test = "Valid!" };
    }

    public override object OnDelete(Secured request)
    {
        return new SecuredResponse() { Test = "Valid!" };
    }
}

If you want, that authentication is only required for GET and PUT requests for example, you have to provide some extra parameters to the Authenticate attribute.

[Authenticate(ApplyTo.Get | ApplyTo.Put)] 

Of course Authenticate can also be placed on top of a service instead on top of a DTO, because it's a normal filter attribute.

The RequiredPermission attribute

ServiceStack also includes a built-in permission based authorization mechanism. To activate the permission mechanism you first need to init it in the app host:

PermissionHandler.Init(this);

Your request dto which requires specific permissions:

[Authenticate()]
//All HTTP (GET, POST...) methods need "CanAccess"
[RequiredPermission("CanAccess")
[RequiredPermission(ApplyTo.Put | ApplyTo.Post, "CanAdd")]
[RequiredPermission(ApplyTo.Delete, "AdminRights", "CanDelete")]
public class Secured
{
    public bool Test { get; set; }
} 

Now the client needs the permissions...

  • "CanAccess" to make a GET request
  • "CanAccess", "CanAdd" to make a PUT/POST request
  • "CanAccess", "AdminRights" and "CanDelete" to make a DELETE request

Normally ServiceStack calls the method bool HasPermission(string permission) in IAuthSession. This method checks if the list List<string> Permissions in IAuthSession contains the required permission.

IAuthSession is stored in a cache client as explained above

You can fill this list in the method OnAuthenticated you've overriden in the first part of this tutorial.

As Authenticate, you can mark services (instead of DTO) with RequiredPermission, too.



  1. Getting Started
    1. Create your first webservice
    2. Your first webservice explained
    3. ServiceStack's new API Design
    4. Designing a REST-ful service with ServiceStack
    5. Example Projects Overview
  2. Reference
    1. Order of Operations
    2. The IoC container
    3. Metadata page
    4. Rest, SOAP & default endpoints
    5. SOAP support
    6. Routing
    7. Service return types
    8. Customize HTTP Responses
    9. Plugins
    10. Validation
    11. Error Handling
    12. Security
  3. Clients
    1. Overview
    2. C# client
    3. Silverlight client
    4. JavaScript client
    5. Dart Client
    6. MQ Clients
  4. Formats
    1. Overview
    2. JSON/JSV and XML
    3. ServiceStack's new HTML5 Report Format
    4. ServiceStack's new CSV Format
    5. MessagePack Format
    6. ProtoBuf Format
  5. View Engines 4. Razor & Markdown Razor
    1. Markdown Razor
  6. Hosts
    1. IIS
    2. Self-hosting
    3. Mono
  7. Security
    1. Authentication/authorization
    2. Sessions
    3. Restricting Services
  8. Advanced
    1. Configuration options
    2. Access HTTP specific features in services
    3. Logging
    4. Serialization/deserialization
    5. Request/response filters
    6. Filter attributes
    7. Concurrency Model
    8. Built-in caching options
    9. Built-in profiling
    10. Messaging and Redis
    11. Form Hijacking Prevention
    12. Auto-Mapping
    13. HTTP Utils
    14. Virtual File System
    15. Config API
    16. Physical Project Structure
    17. Modularizing Services
    18. MVC Integration
  9. Plugins 3. Request logger 4. Swagger API
  10. Tests
    1. Testing
    2. HowTo write unit/integration tests
  11. Other Languages
    1. FSharp
    2. VB.NET
  12. Use Cases
    1. Single Page Apps
    2. Azure
    3. Logging
    4. Bundling and Minification
    5. NHibernate
  13. Performance
    1. Real world performance
  14. How To
    1. Sending stream to ServiceStack
    2. Setting UserAgent in ServiceStack JsonServiceClient
    3. ServiceStack adding to allowed file extensions
    4. Default web service page how to
  15. Future
    1. Roadmap

Clone this wiki locally