I'm making an API and I'm new into it. I thought of this idea for creating an access token. Basically, we encrypt JSON data with a key, turn it to Base64 and return it as the access token. Later, API decrypts that access token and can use the id. E.g.:
login method
:
we check if username/password is correct, if it is, then we get user's id from the database. Then we construct the access token, which will be used in the future API calls, like this:
{"user_id":609, "logintime":"1430428180"}
Later, when the user makes an action, we can use this access token to know about the user. E.g.:
update user info method
: we send data, which needs to be updated and access token, which we got earlier. Then we:
user_id
and logintime
fields.Is this approach any good?
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).
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.
In order for you to be satisfied that a request is valid, you must consider a couple of points.
In order to make sure point 1 holds true over time, an API should also be concerned that a secret key stays secret.
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.
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:
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.
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.
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)
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?
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.