In this answer I'm going to focus more on API security, which I feel is the real question behind the question (prompted by OPs comment on my first answer).
The Purpose of API Keys
API keys are used in cases where a user logging in is difficult, impossible, or otherwise undesirable. The API key is used for Authentication, the "proof of who I am" part of API access. Authorization, or the "I am allowed to do this" is usually stored on the server.
Criteria for Valid API Access
In order for you to be satisfied that a request is valid, you must consider a couple of points.
- Did the request originate from an authorized user?
- Has the request been tampered with in transit?
In order to make sure point 1 holds true over time, an API should also be concerned that a secret key stays secret.
- This request does not damage the validity of future requests.
Please note that although API keys are usually sent as HTTP headers, I'm going to be using GET variables in my examples for simplicity.
Single Key API
Some APIs are set up to give access with a single key. Let's use CEgJu8G483u3
as our example key.
The user would send over a request like
GET /users?apiKey=CEgJu8G483u3 HTTP/1.1
Host: api.bigorg.com
If the API is communicating over HTTP, this is inherently insecure:
- The key is publicly readable, (and therefore usable) by any nosy 3rd party.
- The 3rd party can tamper with the body of the request as much as they like, and the server is unaware.
So in single key API authentication over HTTP, security criteria 1 - 3 violated.
If your single key API is communicating over HTTPS only, then 1 - 3 are still valid and can be considered safe.
Digest, or Signature APIs
This approach is used by Google and Amazon for access to many of their APIs.
When the server grants access to their system, two keys are generated, an identifier and a secret.
ACCESS_IDENTIFIER = 'bill';
ACCESS_SECRET = 'U59g5LcBBZpw';
Once the two keys have been generated, the client and server store a copy of the secret, which is never directly transmitted again.
When a request is made under this system, the identifier is provided with the request (note that the access key can be as complicated as a randomly generated string, or as simple as the id of the user trying to access the system.
Just before the request is sent by the client, a digest of the request is generated and then encrypted using the previously agreed secret. The methods of generating the signature vary, but a common one right now is HMAC.
The request then looks like this
GET /users?identifier=bill&signature=JjU1j1fIH62KG7FCTdZGzK7J HTTP/1.1
Host: api.bigorg.com
Random pseudo-signature used in this example
If the request body is included when generating the signature, you can now authenticate safely.
Note that listening to HTTP traffic is still very very simple, so unauthorized knowledge will still be a problem, but the listening party cannot send their own requests or tamper with yours.
If the request is tampered with, the signature becomes invalid and the request will be rejected.
JSON Web Tokens (your solution)
Your solution is nearly identical to JSON Web Tokens, so I'll just pretend you're using that.
This solution is secure over HTTPS. (DO use HTTPS)
- The request comes from a valid user => They knew the token
- The request has not been tampered with => HTTPS prevents a 3rd party from tampering with a request
- The access key remains a secret => HTTPS prevents a 3rd party from reading your access key
If your API is using HTTP/plaintext, you can use your JSON Web Tokens as the access key, but you'll need to also generate a private secret and use that to add a signature to the request.
Note that I'm not sure how you'll transmit the secret to the client if you're using HTTP. Maybe via snail mail or email?
Conclusion
Your idea has been replicated by very smart people. Congratulations! This means it was a good idea!
Your access key solution is solid provided that you use HTTPS.