Michał Gajek - 19 - Jan 13, 2015

Hi, what would be the smartest way to implement “api key” authorization? 
The thing is it has to run along the credentials auth, and since most of the operations are simple CRUD I’d like to reuse my DTOs.

To be more precise: currently all the request DTOs are marked with [Authenticate] since they’re available for logged users only. 
Now I’d like to make some of them available also for non-logged-in requests, in case the request contains valid api key.

I was considering several ways::

1. custom auth provider
I’m not convinced it’s possible to “authenticate on-the-fly”, i.e. without preceding, separate request calling for authentication ?

2. global filters

3. custom runner

I don’t however know when the authentication checking happens in the order of operations ?

What would be the suggested way to go?

Matt Cowan:

If your logged-in users are also going to pass an api key, then technically you could just remove the Authenticate attribute from those request DTOs and simply check for the Api Key in a request filter like so, right? http://rossipedia.com/blog/2013/03/simple-api-key-authentication-with-servicestack/
If you have a mix of requests, with and without api keys, than there are other options…
Another option I’ve implemented is to combine an api key with a service stack session id (i.e.: mobile clients for example, without a cookie container on the client) where you pass both of those back from the client as headers, and the pre-request filter just populates the servicestack session cookie from the session id header key, and then servicestack does it’s thing as usual. 

You can “Authenticate on-the-fly” by calling the Auth Service in your Service, e.g. from AutoLogin feature in /register service:

I think a good solution for this could be to use a Custom AuthProvider that implements IAuthWithRequest.PreAuthenticate(), e.g from BasicAuthProvider:
where if your AuthProvider implements IAuthWithRequest, the [Authenticate] attribute automatically calls  PreAuthenticate() method. 

To satisfy [Authenticate] your session.IsAuthorized(provider) API just needs to return true. Which by default just calls AuthProvider.IsAuthorized() on your AuthProvider: 

Also you can tell ServiceStack about the sessionId with:
httpReq.Items[“ss-id”] = sessionId;
Or pass it via Cookies (default) or send the ss-* cookie ids as HTTP Headers with a “X-” prefix, e.g “X-ss-id”

Michał Gajek:

Thanks Demis, I wasn’t aware of IAuthWithRequest. Should’ve thought of checking out how Basic Auth works, my fault ;)