Storing authentication tokens in a RESTful API wit

2019-05-09 08:15发布

问题:

I am building a RESTful API with multiple servers and I want to know it's okay to store the access token in a central database server and then, for every request, verifying this access token is valid by querying the database and performing the action given.

If I use sessions for this job, then will it become non RESTful? Like even if I store the session data in database? It's been a confusing idea to me for so long.

回答1:

REST is stateless

REST stands for Representational State Transfer and this architecture was defined by Roy Thomas Fielding in the chapter 5 of his dissertation.

Fielding defined a set of constraints for the REST architecture. One of these constraints is the stateless communication between client and server, defined as following (the highlights are not present in his dissertation):

5.1.3 Stateless

[...] each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]

So, if you keep the session state on the server, you break the stateless constraint. Hence, it's not REST. In REST you won't have a session on the server and, consequently, you won't have session identifiers.

Each request must contain all data to be processed

Each request from client to server must contain all of the necessary information to be understood by the server. With it, you are not depending on any session context stored on the server.

When accessing protected resources that require authentication, for example, each request must contain all necessary data to be properly authenticated/authorized. It means the authentication will be performed for each request.

Have a look at this quote from the RFC 7235 regarding considerations for new authentication schemes:

5.1.2. Considerations for New Authentication Schemes

There are certain aspects of the HTTP Authentication Framework that put constraints on how new authentication schemes can work:

  • HTTP authentication is presumed to be stateless: all of the information necessary to authenticate a request MUST be provided in the request, rather than be dependent on the server remembering prior requests. [...]

And authentication data (credentials) should belong to the standard HTTP Authorization header. From the RFC 7235:

4.2. Authorization

The Authorization header field allows a user agent to authenticate itself with an origin server -- usually, but not necessarily, after receiving a 401 (Unauthorized) response. Its value consists of credentials containing the authentication information of the user agent for the realm of the resource being requested.

Authorization = credentials

[...]

Please note that the name of this HTTP header is unfortunate because it carries authentication data instead of authorization. Anyways, this is the standard header for sending credentials.

Token based authentication

When performing a token based authentication, the tokens are your credentials. In this approach, your hard credentials (username and password) are exchanged for a token that is sent in each request. Again, the authentication must be performed for every request, so you won't take advantage of any stored context on the server.

It's perfectly valid storing your tokens somewhere in your server. And it won't break the stateless constraint of the REST architecture.

Tokens

Basically, the tokens can be opaque (which reveals no details other than the value itself, like a random string) or can be self-contained (like JSON Web Token):

  • Random String: A token can be issued by generating a random string and persisting it to a database with an expiration date and with a user identifier associated to it.

  • JSON Web Token (JWT): Defined by the RFC 7519, it's a standard method for representing claims securely between two parties. JWT is a self-contained token and enables you to store a user identifier, an expiration date and whatever you want (but don't store passwords) in a payload, which is a JSON encoded as Base64. The payload can be read by the client and the integrity of the token can be easily checked by verifying its signature on the server. You won't need to persist JWT tokens if you don't need to track them. Althought, by persisting the tokens, you will have the possibility of invalidating and revoking the access of them. To find some great resources to work with JWT, have a look at http://jwt.io.

There are many databases where you can persist your tokens. Depending on your requirements, you can explore different solutions such as relational databases, key-value stores or document stores.



回答2:

Your RESTful API would need to be stateless. Stateless means, that it should not rely on prior communication, like in the case of authentication and cookies set before the request in question.

That does not mean however that you can not cache some authentication token on the server side, provided, that a client could make a request without it. This all means, that if the client can fall back to standard HTTP authentication on every request, it should still be ok. The goal with this is to enable load balancing, distribution, and no (or limited) memory use on the server side for conversations.

Other than that, you don't really need to follow all the "rules" if you are not planning to use the benefits it provides. You can, if you want, implement it any way you want as long as the tradoffs are known.

Edit: found a previous discussion on the topic: Do sessions really violate RESTfulness?



标签: api rest