Authentication, Authorization and Session Management in Traditional Web Apps and APIs - api

Correct me if I am wrong: In a traditional web application, the browser automatically appends session information into a request to the server, so the server can know who the request comes from. What exactly is appended actually?
However, in a API based app, this information is not sent automatically, so when developing an API, I must check myself if the request comes from an authenticated user for example? How is this normally done?

HTTP Protocol is stateless by design, each request is done separately and is executed in a separate context.
The idea behind session management is to put requests from the same client in the same context. This is done by issuing an identifier by the server and sending it to the client, then the client would save this identifier and resend it in subsequent requests so the server can identify it.
Cookies
In a typical browser-server case; the browser manages a list of key/value pairs, known as cookies, for each domain:
Cookies can be managed by the server (created/modified/deleted) using the Set-Cookie HTTP response header.
Cookies can be accessed by the server (read) by parsing the Cookie HTTP request header.
Web-targeted programming languages/frameworks provide functions to deal with cookies on a higher level, for example, PHP provides setcookie/$_COOKIE to write/read cookies.
Sessions
Back to sessions, In a typical browser-server case (again), server-side session management takes advantage of client-side cookie management. PHP's session management sets a session id cookie and use it to identify subsequent requests.
Web applications API?
Now back to your question; since you'd be the one responsible for designing the API and documenting it, the implementation would be your decision. You basically have to
give the client an identifier, be it via a Set-Cookie HTTP response header, inside the response body (XML/JSON auth response).
have a mechanism to maintain identifier/client association. for example a database table that associates identifier 00112233445566778899aabbccddeeff with client/user #1337.
have the client resend the identifier sent to it at (1.) in all subsequent requests, be it in an HTTP Cookie request header, a ?sid=00112233445566778899aabbccddeeff param(*).
lookup the received identifier, using the mechanism at (2.), check if a valid authentication, and is authorized to do requested operation, and then proceed with the operation on behalf on the auth'd user.
Of course you can build upon existing infrastructure, you can use PHP's session management (that would take care of 1./2. and the authentication part of 4.) in your app, and require that client-side implementation do cookie management(that would take care of 3.), and then you do the rest of your app logic upon that.
(*) Each approach has cons and pros, for example, using a GET request param is easier to implement, but may have security implications, since GET requests are logged. You should use https for critical (all?) applications.

The session management is server responsibility. When session is created, a session token is generated and sent to the client (and stored in a cookie). After that, in the next requests between client and server, the client sends the token (usually) as an HTTP cookie. All session data is stored on the server, the client only stores the token. For example, to start a session in PHP you just need to:
session_start(); // Will create a cookie named PHPSESSID with the session token
After the session is created you can save data on it. For example, if you want to keep a user logged:
// If username and password match, you can just save the user id on the session
$_SESSION['userID'] = 123;
Now you are able to check whether a user is authenticated or not:
if ($_SESSION['userID'])
echo 'user is authenticated';
else
echo 'user isn't authenticated';
If you want, you can create a session only for an authenticated user:
if (verifyAccountInformation($user,$pass)){ // Check user credentials
// Will create a cookie named PHPSESSID with the session token
session_start();
$_SESSION['userID'] = 123;
}

There are numerous way for authentic users, both for Web applications and APIs. There are couple of standards, or you can write your own custom authorization / and or authentication. I would like to point out difference between authorization and authentication. First, application needs to authenticate user(or api client) that request is coming from. Once user has been authenticated, based on user's identity application needs to determine whatever authenticated user has permission to perform certain application (authorization). For the most of traditional web applications, there is no fine granularity in security model, so once the user is authenticated, it's in most cases also and authorized to perform certain action. However, this two concepts (authentication and authorization) should be as two different logical operations.
Further more, in classical web applications, after user has been authenticated and authorized
(mostly by looking up username/password pair in database), authorization and identity info is written in session storage. Session storage does not have to be server side, as most of the answers above suggest, it could also be stored in cookie on client side, encrypted in most cases. For an example, PHP CodeIgniter framework does this by default. There is number of mechanism for protecting session on client side, and I don't see this way of storing session data any less secure than storing sessionId, which is then looked up in session storage on server-side. Also, storing session client-side is quite convenient in distributed environment, because it eliminates need for designing solution (or using already existing one) for central session management on server side.
Further more, authenticating with simple user-password pair does not have to be in all case done trough custom code which looks up matching user-record in database. There is, for example basic authentication protocol , or digest authentication. On proprietary software like Windows platform, there are also ways of authenticating user trough, for an example,ActiveDirectory
Providing username/password pair is not only way to authenticate, if using HTTPS protocol, you can also consider authentication using digital certificates.
In specific use case, if designing web service, which uses SOAP as protocol, there is also WS-Security extension for SOAP protocol.
With all these said, I would say that answers to following question enter decision procedure for choice of authorization/authentication mechanism for WebApi:
1) What's the targeted audience, is it publicly available, or for registered(paying) members only?
2) Is it run or *NIX, or MS platform
3) What number of users is expected
4) How much sensitive data API deals with (stronger vs weaker authentication mechanisms)
5) Is there any SSO service that you could use
.. and many more.
Hope that this clears things bit, as there are many variables in equation.

If the API based APP is a Client, then the API must have option to retrieve/read the cookies from server response stream and store it. For automatic appending of cookies while preparing request object for same server/url. If it is not available, session id cannot be retrieved.

You are right, well the reason things are 'automatic' in a standard environment is because cookies are preferred over URL propagation to keep things pretty for the users. That said, the browser (client software) manages storing and sending the session cookie along with every request.
In the API world, simple systems often just have authentication credentials passed along with every request (at least in my line of work). Client authors are typically (again in my experience) reluctant to implement cookie storage, and transmission with every request and generally anything more than the bare minimum...
There are plenty of other authentication mechanisms out there for HTTP-based APIs, HTTP basic / digest to name a couple, and of course the ubiquitous o-auth which is designed specifically for these things if I'm not mistaken. No cookies are maintained, credentials are part of every exchange (fairly sure on that).
The other thing to consider is what you're going to do w/ the session on the server in an API. The session on a website provides storage for the current user, and typically stores small amounts of data to take load off the db from page to page. In an API context this is less of a need as things are more-or-less stateless, speaking generally of course; it really depends what the service is doing.

I would suggest you send some kind of token with each request.
Dependent on the server and service those can be a JSESSIONID parameter in your GET/POST request or something mature like SAML in SOAP over HTTP in your Web Service request.

Related

CouchDB Proxy Authentication security - user roles confusion

On user auth success my auth server generates a token and passes it to the client.
The docs say that the client has to add the following headers:
X-Auth-CouchDB-UserName: username;
X-Auth-CouchDB-Roles:comma-separated (,) list of user roles;
X-Auth-CouchDB-Token: authentication token.
Does it mean that the client defines his own roles on every request? Why can't he add 'admin' into the list of roles then?
A client is anything that uses or requests resources from a server.
"The client" in this case is your proxy/auth server, not a web browser. (The documentation could probably stand to be clarified a bit.)
So yes, your proxy/auth server, the client to CouchDB, should set that header as appropriate.
By extension, it should also not pass through any X-Auth-Couch headers received from its client (presumably a web browser).
Good observation. Using the JWT Authentication would seem to close this loophole as my understanding is the entire token is signed-over.
That said, in neither case can one avoid:
having to fully trust the entity holding the secret
having to carefully guard against leakage of its headers
The former is sort of unavoidable, as the point of these plugins is to delegate authentication. Either you trust the proxy (or JWT issuer) or you leave those authentication_handlers disabled.
The latter is something that e.g. OAuth 1 hardened itself somewhat against, in that ± the entire request was signed over and one couldn't simply take a couple auth headers from an earlier leaked request and slap them on a new forged request. Nonce and timestamp fields were supposed to be checked to avoid verbatim replays of prior requests as well. (All this was dropped in OAuth 2 for whatever that's worth… and even OAuth 1 had some notable loopholes in practice…)
So in practice either the Proxy or the JWT authentication handlers should be used with care. Assuming a "firewall" of sorts drawn around both your CouchDB and authentication source, then as #Flimzy's answer mentions preventing unexpected headers making their way inwards from outside that boundary — as well as keeping the real headers from leaking outwards — should mitigate most potential abuse.

Token-based authentication: Application vs Server

Just found out that the basic workflow for token-based authentication is as follows:
User requests access by providing username and password
The application validates the credentials and returns a token to the client
The token is then stored on the client and sent with every request henceforth
The server then validates the token and returns private data as a response
Now, I understand the flow more or less, however, I'm having issues with the terms application, client and server. I understand the term server to mean where the API is stored... which is also part of the application. But the application could also be anything from a web app to a mobile app on various platforms... a client in other words.
So isn't it true that the application includes both the server and the client. So what does it mean by each term exactly, in the above context?
On second thoughts... I guess the original token is being generated on the server side, and this is then being returned to the client. Is this true?
Those terms terms are pretty overloaded in software development, so it's always difficult to nail down the exact meaning without focusing in a very specific context. Bear in mind that even authentication can be seen as a very broad context.
I would rephrase your proposed workflow to the following:
User requests access by providing a set of user credentials (we don't have to use passwords all the time, see passwordless authentication out of curiosity).
The authorization server validates the user identity and, if valid, issues an access token.
The client application from which the user started the process receives and stores the issued access token.
The client application calls into a resource server using the access token in order to obtain user associated resources.
Damn, now we have even more terms, but let's try to fix that by providing some definitions.
First, the ones more generic:
Client: An application that obtains information from a server for local use.
Credentials: Usernames, passwords, email addresses—any of a variety of means for communicating parties to generate or obtain security tokens.
(source: Auth0 Identity Glossary)
Then definitions within the context of OAuth 2.0 and/or OpenID Connect:
Authorization server: The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization.
Resource server: The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.
Client: An application making protected resource requests on behalf of the resource owner and with its authorization. The term "client" does not imply any particular implementation characteristics (e.g., whether the application executes on a server, a desktop, or other devices).
(source: RFC 6749)
It's not even useful trying to define application, but what we should conclude from the other definitions is the following:
As you said, a client can range from web, to mobile to event server-side applications.
The role of the authorization server and resource server can be played by the same component, for example, a Web API that has an endpoint protected by HTTP basic authentication that can be used to exchange a pair of username/password credentials with an access token and then all the remaining API endpoints are protected in such way that only allow access if you provide that access token.
Finally, one final note to clarify your last question, yes, the creation of the access tokens need to happen on the server side because the creation of the token will be accompanied by some kind of mechanism that will ensure that the token cannot be tampered with and was in fact created by a very well-know entity. For the case of JWT's this mechanism consists of signing the token which is accomplished by having the server know a secret that no one else knows.

“Shared” authentication for website and RESTful API

Goal: My server needs to direct non-users to a landing/home page, and logged in users to the actual app. When the app is loaded, it will make authenticated HTTP requests to a RESTful API (via Ajax).
I have a RESTful API that needs authentication. On another server I have my website, which also needs authentication, so I can determine whether to display the landing/home page for non-users or the app for logged in users.
Initially I thought it would be enough to implement HTTP Basic Auth for the RESTful API. However, in order to get authentication running for my website too, I would also need to setup authentication there, which would mean duplicating the low-level code to check the credentials in the database in both the REST API and the website servers.
Alternatively, I wondered if the website could authenticate via the RESTful API. For example, in my request handler for POST /login, I could make a GET request to my API, passing along the user credentials from the request body. If the request returns 200 OK, I could sign the user’s session, thus authenticating them. From there onwards, the Ajax requests to the REST API need to be authenticated with the same credentials, so I could:
set a cookie containing the credentials, thus allowing the JavaScript to retrieve the credentials before doing the request (OK with SSL?)
dump the credentials in the served HTML for the web app thus allowing the JavaScript to retrieve the credentials before doing the request (OK with SSL?)
proxy the API through the web app server, where I could retrieve the credentials from the session and add them to the Authorization header of the proxied request?
Alternatively, I imagine I could just share a session between the two servers, although I’ve heard that’s bad practice for RESTful design.
What would be wrong with doing it like this? Is there a better way to meet my goal?
I recently implemented something similar to this (assuming I understand you correctly), and there seemed to be a few viable options.
Have the server side of your web-app always authenticate with a specific username/password when accessing the REST API, ensuring that your web-app is always trusted and assuming that users are properly logged in on the web-app if a request is authenticated as the app.
Pros: Easy to implement, easy to understand, easy to extend for other applications as well (we had a CLI that accessed the same REST API as well).
Cons: It's impossible for the REST API to know which user is actually accessing it. If a trusted client is compromised the whole system is compromised.
Have the server side of your web-app keep user details in the session and authenticate using the users credentials every time you access the REST API.
Pros: Fairly easy to implement (although some authentication mechanisms make it hard to keep hold of the user password - for good reason). The whole procedure is transparent to the REST API.
Cons: You're now storing (for all intents and purposes in clear-text) the username and password of a user in the session of the web-server - one of the most prime targets for attack in the system.
Create an authentication system on the REST API that authenticates a request with a username/password authorization and returns a token that is valid for a limited time.
Pros: More secure, if your web-app is compromised you're not providing the attacker with your users username/passwords, but instead only allowing them a limited time access.
Cons: Much harder to implement. You might need to deal with token timeouts specifically. For purists it also means that your REST implementation (or at least the authentication system) will be arguably "stateful".
What you should implement would depend on your situation. Personally I'd definitely go with the more secure option (the last one), but due to external constraints we were forced to implement the first option in our specific case (with the promise we'd revisit it and upgrade later - unfortunately later never comes).
I think your approach with using Basic HTTP Authentication in REST service and having your app authenticate with the service is perfectly fine. The only caveat here (which I am sure you are aware of), is that your REST service should run over SSL, as Basic HTTP authentication is not very secure - username and password are just Base64 encoded.

REST API Token-based Authentication

I'm developing a REST API that requires authentication. Because the authentication itself occurs via an external webservice over HTTP, I reasoned that we would dispense tokens to avoid repeatedly calling the authentication service. Which brings me neatly to my first question:
Is this really any better than just requiring clients to use HTTP Basic Auth on each request and caching calls to the authentication service server-side?
The Basic Auth solution has the advantage of not requiring a full round-trip to the server before requests for content can begin. Tokens can potentially be more flexible in scope (i.e. only grant rights to particular resources or actions), but that seems more appropriate to the OAuth context than my simpler use case.
Currently tokens are acquired like this:
curl -X POST localhost/token --data "api_key=81169d80...
&verifier=2f5ae51a...
&timestamp=1234567
&user=foo
&pass=bar"
The api_key, timestamp and verifier are required by all requests. The "verifier" is returned by:
sha1(timestamp + api_key + shared_secret)
My intention is to only allow calls from known parties, and to prevent calls from being reused verbatim.
Is this good enough? Underkill? Overkill?
With a token in hand, clients can acquire resources:
curl localhost/posts?api_key=81169d80...
&verifier=81169d80...
&token=9fUyas64...
&timestamp=1234567
For the simplest call possible, this seems kind of horribly verbose. Considering the shared_secret will wind up being embedded in (at minimum) an iOS application, from which I would assume it can be extracted, is this even offering anything beyond a false sense of security?
Let me seperate up everything and solve approach each problem in isolation:
Authentication
For authentication, baseauth has the advantage that it is a mature solution on the protocol level. This means a lot of "might crop up later" problems are already solved for you. For example, with BaseAuth, user agents know the password is a password so they don't cache it.
Auth server load
If you dispense a token to the user instead of caching the authentication on your server, you are still doing the same thing: Caching authentication information. The only difference is that you are turning the responsibility for the caching to the user. This seems like unnecessary labor for the user with no gains, so I recommend to handle this transparently on your server as you suggested.
Transmission Security
If can use an SSL connection, that's all there is to it, the connection is secure*. To prevent accidental multiple execution, you can filter multiple urls or ask users to include a random component ("nonce") in the URL.
url = username:key#myhost.com/api/call/nonce
If that is not possible, and the transmitted information is not secret, I recommend securing the request with a hash, as you suggested in the token approach. Since the hash provides the security, you could instruct your users to provide the hash as the baseauth password. For improved robustness, I recommend using a random string instead of the timestamp as a "nonce" to prevent replay attacks (two legit requests could be made during the same second). Instead of providing seperate "shared secret" and "api key" fields, you can simply use the api key as shared secret, and then use a salt that doesn't change to prevent rainbow table attacks. The username field seems like a good place to put the nonce too, since it is part of the auth. So now you have a clean call like this:
nonce = generate_secure_password(length: 16);
one_time_key = nonce + '-' + sha1(nonce+salt+shared_key);
url = username:one_time_key#myhost.com/api/call
It is true that this is a bit laborious. This is because you aren't using a protocol level solution (like SSL). So it might be a good idea to provide some kind of SDK to users so at least they don't have to go through it themselves. If you need to do it this way, I find the security level appropriate (just-right-kill).
Secure secret storage
It depends who you are trying to thwart. If you are preventing people with access to the user's phone from using your REST service in the user's name, then it would be a good idea to find some kind of keyring API on the target OS and have the SDK (or the implementor) store the key there. If that's not possible, you can at least make it a bit harder to get the secret by encrypting it, and storing the encrypted data and the encryption key in seperate places.
If you are trying to keep other software vendors from getting your API key to prevent the development of alternate clients, only the encrypt-and-store-seperately approach almost works. This is whitebox crypto, and to date, no one has come up with a truly secure solution to problems of this class. The least you can do is still issue a single key for each user so you can ban abused keys.
(*) EDIT: SSL connections should no longer be considered secure without taking additional steps to verify them.
A pure RESTful API should use the underlying protocol standard features:
For HTTP, the RESTful API should comply with existing HTTP standard headers. Adding a new HTTP header violates the REST principles. Do not re-invent the wheel, use all the standard features in HTTP/1.1 standards - including status response codes, headers, and so on. RESTFul web services should leverage and rely upon the HTTP standards.
RESTful services MUST be STATELESS. Any tricks, such as token based authentication that attempts to remember the state of previous REST requests on the server violates the REST principles. Again, this is a MUST; that is, if you web server saves any request/response context related information on the server in attempt to establish any sort of session on the server, then your web service is NOT Stateless. And if it is NOT stateless it is NOT RESTFul.
Bottom-line: For authentication/authorization purposes you should use HTTP standard authorization header. That is, you should add the HTTP authorization / authentication header in each subsequent request that needs to be authenticated. The REST API should follow the HTTP Authentication Scheme standards.The specifics of how this header should be formatted are defined in the RFC 2616 HTTP 1.1 standards – section 14.8 Authorization of RFC 2616, and in the RFC 2617 HTTP Authentication: Basic and Digest Access Authentication.
I have developed a RESTful service for the Cisco Prime Performance Manager application. Search Google for the REST API document that I wrote for that application for more details about RESTFul API compliance here. In that implementation, I have chosen to use HTTP "Basic" Authorization scheme. - check out version 1.5 or above of that REST API document, and search for authorization in the document.
In the web a stateful protocol is based on having a temporary token that is exchanged between a browser and a server (via cookie header or URI rewriting) on every request. That token is usually created on the server end, and it is a piece of opaque data that has a certain time-to-live, and it has the sole purpose of identifying a specific web user agent. That is, the token is temporary, and becomes a STATE that the web server has to maintain on behalf of a client user agent during the duration of that conversation. Therefore, the communication using a token in this way is STATEFUL. And if the conversation between client and server is STATEFUL it is not RESTful.
The username/password (sent on the Authorization header) is usually persisted on the database with the intent of identifying a user. Sometimes the user could mean another application; however, the username/password is NEVER intended to identify a specific web client user agent. The conversation between a web agent and server based on using the username/password in the Authorization header (following the HTTP Basic Authorization) is STATELESS because the web server front-end is not creating or maintaining any STATE information whatsoever on behalf of a specific web client user agent. And based on my understanding of REST, the protocol states clearly that the conversation between clients and server should be STATELESS. Therefore, if we want to have a true RESTful service we should use username/password (Refer to RFC mentioned in my previous post) in the Authorization header for every single call, NOT a sension kind of token (e.g. Session tokens created in web servers, OAuth tokens created in authorization servers, and so on).
I understand that several called REST providers are using tokens like OAuth1 or OAuth2 accept-tokens to be be passed as "Authorization: Bearer " in HTTP headers. However, it appears to me that using those tokens for RESTful services would violate the true STATELESS meaning that REST embraces; because those tokens are temporary piece of data created/maintained on the server side to identify a specific web client user agent for the valid duration of a that web client/server conversation. Therefore, any service that is using those OAuth1/2 tokens should not be called REST if we want to stick to the TRUE meaning of a STATELESS protocol.
Rubens

REST and authentication variants

I am currently working on a REST library for .net, and I would like to hear some opinions about an open point I have: REST and authentication.
Here is an example of an RESTful interface used with the library:
[RestRoot("/user")]
public interface IUserInterface
{
[RestPut("/")]
void Add(User user);
[RestGet("/")]
int[] List();
[RestGet("/get/{id}")]
User Get(int id);
[RestDelete("/delete/{id}")]
void Delete(int id);
}
The server code then just implements the interface and the clients can obtain the same interface through a factory. Or if the client is not using the library a standard HTTP request also works.
I know that there are the major ways of either using HTTP Basic Auth or sending a token to requests requiring authenticated users.
The first method (HTTP Basic Auth), has the following issues (partly web browser specific):
The password is transmitted with every request - even with SSL this has some kind of "bad feeling".
Since the password is transmitted with a request header, it would be easy for an local attacker to look at the transmitted headers to gain the password.
The password is available in the browsers memory.
No standard way to expire user "sessions".
Login with a browser interrupts the look and feel of a page.
The issues for the second method are more focused on implementation and library use:
Each request URI which needs authentication must have a parameter for the token, which is just very repetitive.
There is a lot more code to write if each method implementation needs to check if a token is valid.
The interface will become less specific e.g. [RestGet("/get/{id}")] vs. [RestGet("/get/{id}/{token}")].
Where to put the token: at the end of the URI? after the root? somewhere else?
My idea was to pass the token as parameter to the URL like http:/server/user/get/1234?token=token_id.
Another possibility would be to send the parameter as an HTTP header, but this would complicate usage with plain HTTP clients I guess.
The token would get passed back to the client as a custom HTTP header ("X-Session-Id") on each request.
This then could be completely abstracted from the interface, and any implementation needing authentication could just ask which user the token (if given) belongs to.
Do you think this would violate REST too much or do you have any better ideas?
I tend to believe that authentication details belong in the header, not the URI. If you rely on a token being placed on the URI, then every URI in your application will need to be encoded to include the token. It would also negatively impact caching. Resources with a token that is constantly changing will no longer be able to be cached. Resource related information belongs in the URI, not application related data such as credentials.
It seems you must be targeting web browsers as a client? If so you could investigate using HTTP Digest access authentication or issuing clients their own SSL certificates to uniquely identify and authenticate them. Also, I don't think that session cookies are necessarily a bad thing. Especially when having to deal with a browser. As long as you isolate the cookie handling code and make the rest of the application not rely on it you would be fine. The key is only store the user's identity in the session, nothing else. Do not abuse server side session state.
If you are targeting clients other than the browser then there are a number of approaches you can take. I've had luck with using Amazon's S3 Authentication mechanism.
This is all very subjective of course. Purity and following REST to the letter can sometimes be impractical. As long as you minimize and isolate such behavior, the core of your application can still be RESTful. I highly recommend RESTful Web Services as a great source of REST information and approaches.
I agree with workmad3, if session life time needs to be maintained you should create a session resource. Post on that resource with user credentials (either basic authentication or credentials in the body content) will return unique session id. Delete on /session/{id} will log out the user.
If you want to control the session expiry time. When creating new session (post on session resource) the server will set a cookie on the response (using standard set-cookie header).
The cookie will contain expiry time. The cookie string should be encrypted on the server, so only the server can open that cookie.
Every consequent request to the server will send the session cookie in the cookie header. (it will be done automatically for you if your client is a browser). The server needs to "renew" the cookie for every request, i.e. create new cookie with new expiry time (extend session's timeout).
Remember to clear the cookie when the user calls delete on the session resource.
If you want your application to be more secured you can store the client IP in the cookie itself, so when a request arrives the server can validate that it was sent from the "original" client. But remember that this solution can be problematic when proxies are involved, because the server might "see" all the requests as coming from the same client.
The rest authentication I've seen treats the sessions as a REST resource for creation, destruction etc. and then the session ID is passed to and fro. The ones I've seen tend to use the session cookie for this as it's the only way to secure it really. If you pass the session id in the URL, you don't have any way of really authenticating it came from the correct client.
Authentication is a tricky problem with REST though, as it requires some form of state to be kept outside the URL which infringes upon REST principles of the URL being all that is required to represent state.