What is the advantage of using JWTs over sessions in situations like authentication?
Is it used as a standalone approach or is it used in the session?
JWT doesn't have a benefit over using "sessions" per se. JWTs provide a means of maintaining session state on the client instead of doing it on the server.
What people often mean when asking this is "What are the benefits of using JWTs over using Server-side sessions".
With server-side sessions, you will either have to store the session identifier in a database, or else keep it in memory and make sure that the client always hits the same server. Both of these have drawbacks. In the case of the database (or other centralised storage), this becomes a bottleneck and a thing to maintain - essentially an extra query to be done with every request.
With an in-memory solution, you limit your horizontal scaling, and sessions will be affected by network issues (clients roaming between Wifi and mobile data, servers rebooting, etc).
Moving the session to the client means that you remove the dependency on a server-side session, but it imposes its own set of challenges.
Storing the token securely.
Transporting it securely.
JWT sessions can sometimes be hard to invalidate.
Trusting the client's claim.
These issues are shared by JWTs and other client-side session mechanisms alike.
JWT, in particular, addresses the last of these. It may help to understand what a JWT is:
It is a bit of information. For user sessions, you could include the username and the time when the token expires. But it could conceivably be anything, even the session ID or the user's entire profile (please don't do that though).
It has got a secure signature that prevents malicious parties from generating fake tokens (you need access to the server's private key to sign them and you can verify that they were not modified after they were signed).
You send them with every request, just like a cookie or Authorization Header would be sent. In fact, they are commonly sent in the HTTP Authorization header but using a cookie is fine too.
The token is signed and so the server can verify its origin. We will assume that the server trusts its own ability to sign securely (you should use a standard library: don't try to do it yourself, and secure the server properly).
On the issue with securely transporting the token, the answer is commonly to send it via an encrypted channel, usually httpS.
Regarding securely storing the token in the client, you need to ensure that the bad guys can't get to it. This (mostly) means preventing JS from bad web sites from reading the token to send it back to them. This is mitigated using the same strategies used to mitigate other kinds of XSS attacks.
If you have a need to invalidate JWTs, there are definitely ways this can be achieved. Storing a per-user epoch for only users who have requested to have their "other sessions terminated" is a very efficient method that will probably be good enough. If an application needs per-session invalidation, then a session ID can be maintained in the same way and the "killed tokens" table can still be maintained to be much smaller than the full user table (you only need to retain records newer than the longest allowed token lifetime). So the ability to invalidate the token partially negates the benefit of client-side sessions in that you would have to maintain this session killed state. This will more than likely be a much smaller table than the original session state table, so the lookups are still more efficient though.
One other benefit of using JWT tokens is that it is reasonably easy to implement using libraries available in probably every language you can expect to have it. It is also completely divorced from your initial user authentication scheme - if you move to a fingerprint-based system, you do not need to make any changes to the session management scheme.
A more subtle benefit: Because the JWT can carry "information" and this can be accessed by the client, you can now start doing some smart things. For example, remind the user that their session will be expiring a few days before they are logged out, giving them the option to re-authenticate, based on the expiry date in the token. Whatever you can imagine.
So in short: JWTs answers some of the questions and shortcomings of other session techniques.
"Cheaper" authentication because you can eliminate a DB round trip (or at least have a much smaller table to query!), which in turns enable horizontal scalability.
Tamper-proof client-side claims.
While JWTs does not answer the other issues like secure storage or transport, it does not introduce any new security issues.
A lot of negativity exists around JWTs, but if you implement the same security that you would for other types of authentication, you will be fine.
One final note: It is also not Cookies vs Tokens. Cookies is a mechanism for storing and transporting bits of information and can be used to store and transport JWT tokens too.
The short answer is: None.
A longer version is:
I implemented JWTs for session management after reading this recommendation in the GraphQL docs:
If you aren't familiar with any of these authentication mechanisms, we
recommend using express-jwt because it's simple without sacrificing
any future flexibility.
Implementation was indeed simple as it only added a little bit of complexity. After a while however, I (like you) started wondering what the benefits were. It turns out there are very few (or possibly none) for JWT as far as session management goes, as this blog post explains in detail:
Stop using JWT for sessions
I had a similar question choosing between JWT and token + cache for user authentication.
After reading these articles, it's clear to me the benefits JWT promises do not outpace the problems it brings. So token + cache(Redis/Memcached) is the way to go for me.
Auth Headers vs JWT vs Sessions — How to Choose the Right Auth Technique for APIs
Authentication Techniques for APIs
Stop using jwt for sessions
My two cents, which on the way add some contrast to joepie91's famous blog post.
Considering that today's (and tomorrow's) applications are (mostly) cloud native
There's an economic benefit to Stateless JWT Authentication,
which scales as the application scales:
Cloud applications incur cost with every passing second.
This cost is reduced when users no longer have to authenticate "against" a session store.
Detailed below are some factors which add to the cost of an application when not using JWT:
Database Server
Running a session store 24/7 costs money.
You can not get away with local storage / memory based solutions in the world of K8S, as pods are ephemeral.
Sticky sessions will not fare well for the exact same reason.
Storage
Storing data costs money. storing data in a SSD costs even more.
Session related operations need to be resolved quickly, so an optical drive is not an option.
I/O
Some cloud providers charge money for Disc related I/O.
Download
Circa 2022, it is safe to assume that the API and session store are separate server instances.
Some cloud providers charge for downloading information from one instance to another.
Scaling the session store
This affects all aforementioned factors.
Yet another slightly different perspective that may be useful if you are on AWS.
We had implemented PHP5.x session storage on AWS ElastiCache to centralise session storage across multiple servers.
It worked perfected until we moved to PHP7. It was difficult to configure for PHP7 and we were plagued with intermittent issues where it seemed that the session "failed/mismatched/got a bit confused" for a particular user and then they could not log in on that device until the old session expired.
We moved to using DynamoDb to store the session and no more issues. It is marginally slower but only noticeable at login (session storage) stage.
While this was going on, we implemented AWS cognito to replace our authentication and started to use the API-Gateway to deliver content via lambda python functions.
We use the PHP SDK to authenticate with Cognito and then we store the JWT in a cookie but still also use the PHP session to keep our legacy code working.
Now we have two stacks and the best of both worlds: PHP7 does it's bit and gets the main content to the user (very quickly). Then JS takes over and provides additional content using the JWT.
What I think is great about JWT is the fact that it can be passed around between these two stacks and used to authenticate the user in both cases.
Now we are wondering if it is worthwhile taking the plunge and switching over to the new JWT system entirely?
In PHP, we still use our legacy session but we also pass the token to cognito to authenticate it. It's a bit of extra security that is probably not necessary but it gives a warm cozy feeling. Then again, there are costs and maintenance with dynamoDb that could be saved.
In session authentication (or stateful authentication) you can store more data than token. But you have to store the session object somewhere and this makes the authentication centralized. Also, you need to have extra memory to store the sessions and this will give extra work to manage this memory. If your application grows, now you have to implement different designs based on your needs, implementing a session cache service, and storing the session on web application or database.
In Jwt or in general Stateless authentication, you do not store anything. You send the token with the request header. This makes it decentralized authentication. The drawback of this authentication is token revocation. Each token has an expiry time and if your token is stolen, it will be valid till it expires. You have to implement logic to minimize the risk.
Related
I have a set of APIs purely for my own app, so I just have a simple API to create access token, when user provided the email and password
/api/access_token (return access_token when email and password matched)
The access_token was saved and matched against in the database sessions table with the expiry field, for now, the expiry is one week, so user need to re-login after one week.
So far it worked fine, but if I want to have the remember me functions as those Facebook / Twitter app, which mean user don't need to re-login so often, which I assume they are using something like the OAuth refresh access tokens approach.
Since I am not using those OAuth stuffs, given my current design and setup, what would be the simplest and secure way to achieve the same functionalities?
You have a few options to choose from, I'll try provide an overview. There is a significant difference depending on whether the client is a browser or a mobile app.
First, for browsers, plain old session tokens are generally more secure than JWT or other structured tokens. If your requirements don't force you to store stuff on or flow stuff through the client, then don't.
The most secure option for a browser client (single page javascript app or plain old rendered app) is the following:
When the user hits the login endpoint with their username and password, the endpoint creates a random session id, and stores it in a database.
The server sends back the session token as a httpOnly cookie, thus it protects it from potential XSS.
The client then automatically includes the session token in all subsequent requests.
Additional data can be stored server-side for the session.
This above is basically plain old stateful session management. The length of such a session should be limited, but if your requirements and threat model allows, you can make this a very long session, like months even if you want, but be aware of the associated risk. These tokens can be inspected in the browser and stolen from a user if not else then by physical access to the client, so a very long expiry has its risks.
Note that mobile apps can pretty much just do the same. The difference is that mobile apps do have a way to store secrets more securely on current mobile platforms. As the storage is protected by user login, and also segregated by app, a session id stored correctly in a mobile app has a lot less chance to be compromised, meaning a longer expiry presents lower risk than in case of a plain browser.
You can also implement a refresh token. However, the point in refresh tokens is that you want to store them in a different way than the other token. If they are stored the same way, a refresh token provides very little benefit (sure, it won't be sent with every request, but that's not where it will get compromised anyway, TLS / HTTPS is secure for transport). In case of OAuth / OpenID, the authentication server can for example set the refresh token on its own origin (like login.example.com), and then forward the user to the app with an authorization code for example, which can be exchanged by the application (service provider) for an access token, that is set for the application domain (like app.example.com). This way, the two tokens have different access models, a compromised app will not leak the refresh token, even if the current access token is leaked, and the access token can be refreshed relatively seamlessly.
If you don't have a separate login endpoint, all this doesn't make a lot of sense, except in one very specific case. Thinking about browser clients, you can set a refresh token in a httpOnly cookie, so it's protected from XSS, and you can store an access token in something like localStorage. However, why would you do this? Pretty much the only reason you would do this is if you need to send the access token to some other origin, which is the whole point in OAuth and OpenID.
You could also argue that statelessness is a benefit of such tokens. In reality, the vast majority of services don't actually benefit from statelessness, but it makes some features technically impossible (like for example forcing logout, as in terminating existing user sessions - for that, you would have to store and check revoked tokens, which is not stateless at all).
Ok so to provide "remember me" as in auto-login, you basically have two options. You can either just make your sessions very long (like months, years, forever), which is more ok for mobile apps as they can store the token more securely than a browser, or you can implement some kind of a refresh mechanism. As discussed above, this only makes sense if the refresh token is stored and accessed differently than the session token.
In case of a browser app with a single origin (no auth/login service), this is not really possible, there is no real separation, and a refresh token doesn't make a lot of sense. If you want an auth service, you should be looking into OpenID Connect (OIDC).
For a mobile app, what you could do is store a refresh token in secure storage, and use access tokens from the localStorage of something like a webview, but unless there are very specific requirements, this would likely not be worth the complexity, as you could just store a longer lived session token in the secure storage.
As for remember me, you can just implement it in a way that users that choose to be remembered will have a sessino token with a longer expiry - as you already store expiry for each token in your database, everything is already set up for that, and in many usecases this is fine. There is some additional risk for users that choose this, but there is also some additional benefit in terms of convenience - it's always a compromise.
What you can consider doing to make such very long sessions more secure is check and store some kind of a device fingerprint (there are Javascript libs for this). If you have a very long lived session, but only valid for a specific fingerprint (ie. it only works from the same device), that mitigates the risk somewhat. However, almost everything that is used for a device fingerprint can be spoofed by an attacker, but it still makes it significantly harder for an attacker to steal a session, and you can have approrpiate monitoring in place for attempts. There will be UX considerations too, like the fingerprint might change with browser/app updates and so on, but it's still worth it sometimes.
Another new-ish feature you could consider is WebAuthn and Passkey, for passwordless authentication. These basically provide device authentication, a key will be seamlessly generated for the user on the specific device, and that will be used for logging in. UX is now getting better, but there are still challenges. The way device authentication translates into user authentication is that the key is associated with the user session (the user "unlocks" the keystore, ie. decrypts the stored keys upon login, with their login credentials). This can also provide "remember me" (seamless auto-login), but in my experience the technology is not fully ready yet, though it's getting there.
While I fully agree with the comments above, I would like to create a clear solution in the minds of other readers by giving a clear and directly understandable concrete answer to your problem.
Let's take an example for JWT;
RefreshToken is the structure that will be activated when the AccessToken expires and will complete the Authentication phase without the need for login. The logic is as follows: AccessToken has a very short lifespan compared to RefreshToken. This time is up to you. The purpose is this: AccessToken is destroyed in short time intervals so that it does not fall into the hands of anyone. However, for this reason, the need to login to the system again arises. To make it easier to login again; When you take the previous AccessToken, you will take another token (RefreshToken) that can be used for a longer period of time and keep it in your pocket. The part I call your pocket depends on the technology you use. For example, you can also keep it in the browser. Keeping it in a browser is not an ideal method (It would be DB, file, cache what you use), because it can create a security vulnerability when someone has access for browsers. So where to keep it depends on the situation and you decide, but; RefreshToken will be activated when AccessToken expires on your client Login functionality.
It has become customary to set a default period of 100 days for RefreshToken. however, this time is up to you, depending on your application business preference.
I found a very clear example when I googled, you can check it below.
https://www.c-sharpcorner.com/article/jwt-authentication-with-refresh-tokens-in-net-6-0/
You can use the same functionality on your serverside code for all your clients (mobile or web not important)
Our system architecture is like an admin can assign permissions on the user level. we are using JWT token for authorization, previously we use roles, and roles are added in payload on sever side we check that role and allow/disallow accordingly without hitting the database. But when we add permissions in the JWT token its payload is too heavy and affects the network traffic.
So my question is what is the best practice to deal with user base permissions in JWT token.
I don't think there is a "best practice" for this as it doesn't sound advisable to store a user's permissions in a JWT, because of the following:
Since a JWT must contain all the information necessary to execute a request, if at any given time a user has permissions removed, he will continue to have them for a period of time as long as his JWT has not expired. That is, using the approach you describe, adding or removing permissions from a user is not an effect that occurs immediately, so it is necessary to develop mechanisms so that the effect of those changes is immediate. Additionally, I consider that a user's permissions can be classified as sensitive information, and it is not recommended to store sensitive information in a JWT (since anyone can see it).
If you want to continue doing that, you can assign identifiers to permissions (such as small numbers) and store those identifiers and permissions in your server's RAM (for example, using a dictionary or hash table). Finally, in the JWT you only have to store the identifiers of the permissions, thus saving as much space as possible. This way there is no need to hit the database.
You really have two options if you are using JWTs and not some sort of session-based old framework.
You store permissions in the JWT. As pointed out there are 2 main issues with this. Firstly it becomes stale, possibly quickly. Secondly this potentially bloats the JWT depending on how many permissions you have in your application. Also, for multitenant applications you now make it significantly more awkward to switch between tenants on the fly. Because now you need to reissue a token (somehow force a logout/login) whenever the user changes tenants.
You handle permissions through a network call to a server (probably the login server) which remotely handles authorization. This adds overhead but keeps things responsive. The only downside is really network traffic. It may sound like there's ways around this but there really isn't and people have accepted the large amount of added traffic.
IMO do what is the least you need. There are bandaids for JWT staleness such as short refresh timers. There are also ways to work with bloated JWTs such as strings created from enum flags. If you do not need immediate refreshing of permissions or lots of them there is nothing wrong from a practicality standpoint of putting authorization data in the JWT.
If the above does not apply, then you need to setup a network call system to handle the authorization. Ideally this is faster/leaner than http network calls.
As an example I use gRPC calls. Example working repository you can see/run is at https://github.com/Perustaja/PermissionServerDemo
I wrote an asp.net core 3.0 web api where I am using JWT tokens to authenticate a user. Once the user gets token, he/she can use it until it expires.
What I have done is that I have also stored this token in-memory on authentication, to get other minimal details e.g. username, token generated at and "token".
My first question is that is it a good practice? since tokens are stateless and therefore saves server side from the hassle of maintaining it.
My second question is that if it is acceptable to do so, then how do I remove this token information from in-memory once a token expires.
If I am not storing this token in memory, how to extract information like "get a list of all logged-in users".
Yes, it is a good practice to cache the JWT in memory cache like Redis or simple in-memory cache. The newly created tokens are cached in memory with cache eviction time same as token expiration time.
When a request comes in to validate token, its first checked whether it exists in memory cache, if not will be looked in to persistent storage like db.
When the user invalidates token(ie logged out), it should be removed from cache and update the state to invalidated in db.
In a distributed application, its a challenge to maintain the state. For this reason, its better to have separate caching layer backed by redis. In this way, we can maintain the application stateless.
In addition to token expiration time, you may want to add additional check for validation, depends on the content of JWT like (aud claim, signature verification etc).
To retrospect the content of JWT token , you can use tools like below
https://devtoolzone.com/decoder/jwt
Cheers,
Lakshmanan
When you say "in memory", does that mean locally on the client machine or somewhere in the server? I'm going to assume you mean client-side for their use.
I'm currently using JWT myself, so here are my recommendations:
1) Save the tokens in session storage.
2) Just empty the session (or wherever you're storing it).
3) You'll definitely need to store it somewhere if you want to access it. But getting a list of all users sounds like you want the data on the back-end. You can keep track of that on a back-end server, but usually these tokens are handled and persisted into databases. But even on a back-end server, you can just have a array of Client objects to track which ones are logged in (i.e. which ones have unexpired tokens).
The typical practice involves generating two tokens (auth token and refresh token) and then checking them against a database when the user submits a token for authentication.
I have started to design a RESTful API and I'm thinking about how to handle authentication. I want to use some kind of authentication token but I can't use OAuth o similar infrastructures so I have to handle it myself.
One of the requirements for this API is that it must have good performance, enough to handle a high volume of requests before there is the need to scale; my concern is how to make on each request the time needed to verify the token (integrity, expiration, IP Address, etc...) as little as possibile.
I suppose the token should some kind of hash and not an encrypted string containing the user information because the decryption time would be to heavy.
I've read that I could store the tokens in an in-memory hashtable where the key is the token and the value is the user info needed to process the request, but how can I make this work in a clustered environment where there will be an hashtable on each "node"?
Should I put tokens on a DB table an hit the DB every time also Handling manually the retention of expired tickets?
Probably it's not that important for the question but I'm using Spring MVC for the RESTfull API.
Thanks in advance.
I solved my problem by using both an in-memory cache and a db cache. Here is a summary of my solution that may help anyone with the same task.
the user logs in and in that moment a unique key is generated and sent back to the user.
that login token (which is basically a GUID with some processing) is also store in a db table with additional info like exipiration and with the user's info and roles. the same pieces of information are also store in memory (google guava hashtable where the token is the key)
the token must be passed along with every api call in the authorization token as #ipa suggested
the server code checks if the token is in its memory cache the user info are already available otherwise (e.g. the api call is done on another node in the cluster) the token is search in the token db
once the token is found you can check expiration, roles, etc...
This grants a good level of performance and security, the token can be generated with any arbitrary algorithm even a relative slow one since you don't have to recalculate it on every api call. Also this works with a stateless service wich can be scaled up horizontally.
I assume you use https and therefore all the traffic is encrypted. I'd suggest one of the following principles.
Basic Authentication
You can add the credentials in the Authorization header of the request. This credentials are encoded with Base64 (see below). This credentials could be sent on every request and then checked with your DB. To get this faster and less IO intensive you can still use a cache. Once I implemented an API like this without a cache and was able to handle thousands of requests per second.
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Authorization Token
There are different ways to implement your idea with a token. A common one is that every API user has his own token usually called api key which never expires. Another one is that you first have to authorize (Basic Authentication) and then get a token back which expires. This one is then used as api key for a certain time.
Either way you have to decide whether to use a cache or not. I would keep it simple and go for basic authentication and check the db every time. Almost every framework has very good support for this approach because it's simple http. If this causes performance issues (I'd recommend performance tests anyway) try to add the table with your credentials to the JPA cache. If you want to implement something with expiring tokens have a look at Infinispan.
You can store token in Redis. If you are going to store it in DB, make sure you optimise server (if you are managing it) for read operations. I have couple of implementation where folks have used key value store as well. Hashtable is also good idea.
Overview
I'm looking to create a (REST) API for my application. The initial/primary purpose will be for consumption by mobile apps (iPhone, Android, Symbian, etc). I've been looking into different mechanisms for authentication and authorization for web-based APIs (by studying other implementations). I've got my head wrapped around most of the fundamental concepts but am still looking for guidance in a few areas. The last thing I want to do is reinvent the wheel, but I'm not finding any standard solutions that fits my criteria (however my criteria my be misguided so feel free to critique that as well). Additionally, I want the API to be the same for all platforms/applications consuming it.
oAuth
I'll go ahead and throw out my objection to oAuth since I know that will likely be the first solution offered. For mobile applications (or more specifically non-web applications), it just seems wrong to leave the application (to go to a web-browser) for the authentication. Additionally, there is no way (I am aware of) for the browser to return the callback to the application (especially cross-platform). I know a couple of apps that do that, but it just feels wrong and gives a break in the application UX.
Requirements
User enters username/password into application.
Every API call is identified by the calling application.
Overhead is kept to a minimum and the auth aspect is intuitive for developers.
The mechanism is secure for both the end user (their login credentials are not exposed) as well as the developer (their application credentials are not exposed).
If possible, not require https (by no means a hard requirement).
My Current Thoughts on Implementation
An external developer will request an API account. They will receive an apikey and apisecret. Every request will require at minimum three parameters.
apikey - given to developer at regisration
timestamp - doubles as a unique identifier for each message for a given apikey
hash - a hash of the timestamp + the apisecret
The apikey is required to identify the application issuing the request. The timestamp acts similarly to the oauth_nonce and avoids/mitigates replay attacks. The hash ensures that request was actually issued from the owner of the given apikey.
For authenticated requests (ones done on the behalf of a user), I'm still undecided between going with an access_token route or a username and password hash combo. Either way, at some point a username/password combo will be required. So when it does, a hash of several pieces of information (apikey, apisecret, timestamp) + the password would be used. I'd love feedback on this aspect. FYI, they would have to hash the password first, since I don't store the passwords in my system without hashing.
Conclusion
FYI, this isn't a request for how to build/structure the API in general only how to handle the authentication and authorization from solely within an application.
Random Thoughts/Bonus Questions
For APIs that only require an apikey as part of the request, how do you prevent someone other than the apikey owner from being able to see the apikey (since sent in the clear) and make excessive requests to push them over usage limits? Maybe I'm just over thinking this, but shouldn't there be something to authenticate that a request was verified to the apikey owner? In my case, that was the purpose of the apisecret, it is never shown/transmitted without being hashed.
Speaking of hashes, what about md5 vs hmac-sha1? Does it really matter when all of the values are hashed with with sufficiently long data (ie. apisecret)?
I had been previously considering adding a per user/row salt to my users password hash. If I were to do that, how could the application be able to create a matching hash without knowing the salt used?
The way I'm thinking about doing the login part of this in my projects is:
before login the user requests a login_token from the server. These are generated and stored on the server on request, and probably have a limited lifetime.
to login the application calculates the hash of the users password, then hashes the password with the login_token to get a value, they then return both the login_token and the combined hash.
The server checks the login_token is one that it has generated, removing it from its list of valid login_tokens. The server then combines its stored hash of the user's password with the login_token and ensures that it matches the submitted combined token. If it matches you have authenticated your user.
Advantages of this are that you never store the user's password on the server, the password is never passed in the clear, the password hash is only passed in the clear on account creation (though there may be ways around this), and it should be safe from replay attacks as the login_token is removed from the DB on use.
That's a whole lot of questions in one, I guess quite a few people didn't manage to read all the way to the end :)
My experience of web service authentication is that people usually overengineer it, and the problems are only the same as you would encounter on a web page. Possible very simple options would include https for the login step, return a token, require it to be included with future requests. You could also use http basic authentication, and just pass stuff in the header. For added security, rotate/expire the tokens frequently, check the requests are coming from the same IP block (this could get messy though as mobile users move between cells), combine with API key or similar. Alternatively, do the "request key" step of oauth (someone suggested this in a previous answer already and it's a good idea) before authenticating the user, and use that as a required key to generate the access token.
An alternative which I haven't used yet but I've heard a lot about as a device-friendly alternative to oAuth is xAuth. Have a look at it and if you use it then I'd be really interested to hear what your impressions are.
For hashing, sha1 is a bit better but don't get hung up about it - whatever the devices can easily (and quickly in a performance sense) implement is probably fine.
Hope that helps, good luck :)
So what you're after is some kind of server side authentication mechanism that will handle the authentication and authorisation aspects of a mobile application?
Assuming this is the case, then I would approach it as follows (but only 'cos I'm a Java developer so a C# guy would do it differently):
The RESTful authentication and authorisation service
This will work only over HTTPS to prevent eavesdropping.
It will be based on a combination of RESTEasy, Spring Security and CAS (for single sign on across multiple applications).
It will work with both browsers and web-enabled client applications
There will be a web-based account management interface to allow users to edit their details, and admins (for particular applications) to change authorisation levels
The client side security library/application
For each supported platform (e.g.
Symbian, Android, iOS etc) create a
suitable implementation of the
security library in the native
language of the platform (e.g. Java,
ObjectiveC, C etc)
The library
should manage the HTTPS request
formation using the available APIs
for the given platform (e.g. Java
uses URLConnection etc)
Consumers of the general authentication and
authorisation library ('cos that's
all it is) will code to a specific
interface and won't be happy if it
ever changes so make sure it's very
flexible. Follow existing design
choices such as Spring Security.
So now that the view from 30,000ft is complete how do you go about doing it? Well, it's not that hard to create an authentication and authorisation system based on the listed technologies on the server side with a browser client. In combination with HTTPS, the frameworks will provide a secure process based on a shared token (usually presented as a cookie) generated by the authentication process and used whenever the user wishes to do something. This token is presented by the client to the server whenever any request takes place.
In the case of the local mobile application, it seems that you're after a solution that does the following:
Client application has a defined Access Control List (ACL) controlling runtime access to method calls. For example, a given user can read a collection from a method, but their ACL only permits access to objects that have a Q in their name so some data in the collection is quiety pulled by the security interceptor. In Java this is straightforward, you just use the Spring Security annotations on the calling code and implement a suitable ACL response process. In other languages, you're on your own and will probably need to provide boilerplate security code that calls into your security library. If the language supports AOP (Aspect Oriented Programming) then use it to the fullest for this situation.
The security library caches the complete list of authorisations into it's private memory for the current application so that it doesn't have to remain connected. Depending on the length of the login session, this could be a one-off operation that never gets repeated.
Whatever you do, don't try to invent your own security protocol, or use security by obscurity. You'll never be able to write a better algorithm for this than those that are currently available and free. Also, people trust well known algorithms. So if you say that your security library provides authorisation and authentication for local mobile applications using a combination of SSL, HTTPS, SpringSecurity and AES encrypted tokens then you'll immediately have creditibility in the marketplace.
Hope this helps, and good luck with your venture. If you would like more info, let me know - I've written quite a few web applications based on Spring Security, ACLs and the like.
Twitter addressed the external application issue in oAuth by supporting a variant they call xAuth. Unfortunately there's already a plethora of other schemes with this name so it can be confusing to sort out.
The protocol is oAuth, except it skips the request token phase and simply immediately issues an access token pair upon receipt of a username and password. (Starting at step E here.) This initial request and response must be secured - it's sending the username and password in plaintext and receiving back the access token and secret token. Once the access token pair has been configured, whether the initial token exchange was via the oAuth model or the xAuth model is irrelevant to both the client and server for the rest of the session. This has the advantage that you can leverage existing oAuth infrastructure and have very nearly the same implementation for mobile/web/desktop applications. The main disadvantage is that the application is granted access to the client's user name and password, but it appears like your requirements mandate this approach.
In any case, I'd like to agree with your intuition and that of several other answerers here: don't try to build something new from scratch. Security protocols can be easy to start but are always hard to do well, and the more convoluted they become the less likely your third-party developers are to be able to implement against them. Your hypothetical protocol is very similar to o(x)Auth - api_key/api_secret, nonce, sha1 hashing - but instead of being able to use one of the many existing libraries your developers are going to need to roll their own.
Super late to the party but I wanted to throw in some additional points to consider for anyone interested in this issue. I work for a company doing mobile API security solutions (approov) so this whole area is definitely relevant to my interests.
To start with, the most important thing to consider when trying to secure a mobile API is how much it is worth to you. The right solution for a bank is different to the right solution for someone just doing things for fun.
In the proposed solution you mention that a minimum of three parameters will be required:
apikey - given to developer at registration
timestamp - doubles as a unique identifier for each message for a given apikey
hash - a hash of the timestamp + the apisecret
The implication of this is that for some API calls no username/password is required. This can be useful for applications where you don't want to force a login (browsing in online shops for example).
This is a slightly different problem to the one of user authentication and is more like authentication or attestation of the software. There is no user, but you still want to ensure that there is no malicious access to your API. So you use your API secret to sign the traffic and identify the code accessing the API as genuine. The potential problem with this solution is that you then have to give away the secret inside every version of the app. If someone can extract the secret they can use your API, impersonating your software but doing whatever they like.
To counter that threat there are a bunch of things you can do depending on how valuable the data is. Obfuscation is a simple way to make it harder to extract the secret. There are tools that will do that for you, more so for Android, but you still have to have code that generates your hash and a sufficiently skilled individual can always just call the function that does the hashing directly.
Another way to mitigate against excessive use of an API that doesn't require a login is to throttle the traffic and potentially identify and block suspect IP addresses. The amount of effort you want to go to will largely depend upon how valuble your data is.
Beyond that you can easily start getting into the domain of my day job. Anyway, it's another aspect of securing APIs that I think is important and wanted to flag up.