ServiceStack Different Security based on routes

Viewed 50

We have a ServiceStack host, in which we have modularised the services. In addition we have a custom authentication solution based on the Basic Authentication. But what we would like to do is have different authentication methods for different services, maybe based on routes? Is this possible?

Secondly, is it possible to assign a common route prefix based on the service? As I said we have modularised our services, and in the AppHost definition we enter the assemblies of the different services, but is it possible to change the route prefix, i.e. Service1 to localhost/api1/servicemethods, Service2 to localhost/api2/servicemethods etc.?

2 Answers

You can limit that a Service should only authenticate with a specific provider by specifying the provider name in the [Authenticate] attribute, e.g:

[Authenticate(AuthenticateService.ApiKeyProvider)]
public class ApiKeyAuthServices : Service
{
    public object Any(ApiKeyOnly request) => ...;
}

[Authenticate(AuthenticateService.JwtProvider)]
public class JwtAuthServices : Service
{
    public object Any(JwtOnly request) => ...;
}

Otherwise inside your Service you can inspect how the request was authenticated by looking at base.SessionAs<AuthUserSession>().AuthProvider.

For defining dynamic routes have a look at:

Although ServiceStack isn't designed to define different sets of Apps within the same AppHost so if that's what you're trying to do I'd recommend instead having different AppHosts and using the Service Gateway for any Service-to-Service communication.

Many thanks for your reply. I must be doing something fundamentally wrong, even though I have registered two custom authproviders, both based on the BasicAuthProvider, using AuthenticateService.GetAuthProviders() returns an empty array.

This is the code I use to register the AuthProviders, and they both allow me to login, so I know they are working.

Plugins.Add(new AuthFeature(() => new CustomUserSession(),
                new IAuthProvider[] {
                    new RMCredentialsAuthProvider(),
                    new RMKOTAuthProvider()
                }));

The code from one of the custom providers is

public class RMKOTAuthProvider : BasicAuthProvider
{
    #region Public Constructors

    public RMKOTAuthProvider() : base()
    {
        
    }

    #endregion Public Constructors

    #region Public Methods

    public override Task<IHttpResult> OnAuthenticatedAsync(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo, CancellationToken token = default)
    {
        session.FirstName = session.UserAuthName;
        session.Roles = new List<string>
        {
            "KOT"
        };

        authService.SaveSessionAsync(session, SessionExpiry);

        return base.OnAuthenticatedAsync(authService, session, tokens, authInfo, token);
    }

    public override Task<bool> TryAuthenticateAsync(IServiceBase authService, string userName, string password, CancellationToken token = default)
    {
        try
        {
            if (userName.IsNullOrEmpty() || password.IsNullOrEmpty())
                return Task.FromResult(false);

            var result = VerifyUser(username, password);

            return Task.FromResult(result);
            
        }
        catch (InvalidCastException)
        {
            return Task.FromResult(false);
        }
    }

    #endregion Public Methods
}

Can you please explain what step I am missing such that GetAuthProviders() can list the providers, and I can use the metadata you described earlier.

Many thanks in advance for your help with this.

Related