You would want to combine the authenticate and resource request steps into one single request. Not only is this faster, it is also safer than your implementation. Consider the following scenario:
- User authenticate to the server. Result is success.
- Authentication is changed. (e.g. user changes password, admin decides to lock the user account, etc.)
- User makes a request using the sessionID in step 1.
To ensure that the user is not granted access to the resource, you'd want to authenticate the user precisely at step 3. But that doesn't make sense, you've already authenticated this user previously in step 1...
HTTP, in is core, is designed exactly to do this. There are various ways to pass authentication information along with the request, such as:
- Write the authentication information in the content (stupid, but works)
- Include authentication in the url, e.g. example.com/pic/123?sessionID=abc (better, but makes your url ugly and long)
- Store session info in cookie (better, but what if the client does not support cookie? what about cookie expiration?)
- Authenticate HTTP header (my best personal recommendation)
HTTP itself has an authenticate header meant to be compatible with "basic authentication" (it is well defined, look it up if you're interested). But you can implement your own custom header.
Any cache lookup is bound to be slow (compared to computation), so you should omit the cache for the authentication part all together. Your server should be stateless; i.e. do not keep track of login sessions. How do you know if the sessionID is valid? Put a timestamp on it. And to avoid others faking the sessionID, sign it as well.
So, your HTTP request would look something like this (pseudo code):
var request = new HttpRequest();
request.url = "example.com/pic/123";
request.Headers["CustomAuth"] = "id=abc&t=123456789&s=01de45890a";
Implement your own signing method, sort of like a hash function (you can use HMAC), and keep the key securely on the server. If the signature matches, you know you've signed this previously at the login, and it has to be from your server. A timestamp helps you detect session expiration and also protect against replay attacks.
Now in your server, do something like this:
public void Get(){
var authHeader = Request.Headers["CustomAuth"];
if(!validate(authHeader)){
Response.StatusCode = 404;
Response.End();
}else{
//something else
}
}
If you need to do login + session authenticate + resource request in one request, then there're simply just 2 ways for authentication. Users can either provide a username/password combination, or a session key. Think about this scenario, which comes from an API I worked on:
- user register with username/password combo
- server responds registration success / failure (e.g. username already taken)
- if it was a success, user now logins with username/password combo
- server returns a session token
Wouldn't it be simpler (and faster) if we do it this way:
- user register with username/password combo
- if it is success, respond "reg success" and "sessionToken=xxxxxx". if it is failure, respond "reg failure".
I hope this give you some idea.