-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication and authorization
ServiceStack supports basic authentication and OAuth authentication out of the box. There exists a project template/example which shows, what you have to do, to enable OAuth and basic authentication.
In the example project, most of the magic happens in the AppHost.
//Register all Authentication methods you want to enable for this web app.
AuthService.Init(this, () => new CustomUserSession()
new AuthConfig[] {
new CredentialsAuthConfig(), //HTML Form post of UserName/Password credentials
new TwitterAuthConfig(appSettings), //Sign-in with Twitter
new FacebookAuthConfig(appSettings), //Sign-in with Facebook
new BasicAuthConfig(), //Sign-in with Basic Auth
});Then the routes for authentication are registered:
Routes
//Using ServiceStack's built-in Auth and Registration services
.Add<Auth>("/auth")
.Add<Auth>("/auth/{provider}")
.Add<Registration>("/register")When the client now tries to authenticate with a GET http://localhost/auth request and the auth succeeded, the client will have two cookies (with an unique session id) which identify the client. With these two cookies, the server knows, that the client is authenticated and allows the access to secured web services.
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());
//Configure an alt. distributed peristed cache that survives AppDomain restarts. e.g Redis
//container.Register<IRedisClientsManager>(c => new PooledRedisClientManager("localhost:6379"));If you've got multiple server which run the same ServiceStack service, you can use Redis to share the sessions between these servers.
But how do you implement custom authenticate logic?
Then you need to override AuthUserSession like here.
You can override the TryAuthenticate method to provide custom authentication logic against your database or something like that:
/// <summary>
/// Create your own strong-typed Custom UserSession where you can add additional UserSession
/// fields required for your application. The base class is automatically populated with
/// User Data as and when they authenticate with your application.
/// </summary>
public class CustomUserSession : AuthUserSession
{
public override bool TryAuthenticate(IServiceBase oAuthService, string userName, string password)
{
//Custom auth logic...
//Return true if username and password are valid, otherwise return false.
}
}AuthUserSession is an implementation IAuthSession
This custom user session needs to be passed to the init method of the AuthService:
AuthService.Init(this, () => new CustomUserSession(), ...);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.
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)] 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 TryAuthenticate you've overriden in the first part of this tutorial. Alternatively you can also override the method HasPermission.
- Why ServiceStack?
- What is a message based web service?
- Advantages of message based web services
- Why remote services should use separate DTOs
- Getting Started
- Reference
- Clients
- Formats
- View Engines 4. Razor & Markdown Razor
- Hosts
- Security
- Advanced
- Configuration options
- Access HTTP specific features in services
- Logging
- Serialization/deserialization
- Request/response filters
- Filter attributes
- Concurrency Model
- Built-in caching options
- Built-in profiling
- Form Hijacking Prevention
- Auto-Mapping
- HTTP Utils
- Virtual File System
- Config API
- Physical Project Structure
- Modularizing Services
- MVC Integration
- Plugins 3. Request logger 4. Swagger API
- Tests
- Other Languages
- Use Cases
- Performance
- How To
- Future