简体   繁体   中英

Suggestion on Api Access with Express-Gateway, and User authentication with JWT

I have a server in Express that exposes some APIs to a web application. I am looking for a good way to manage both final users and 3rd parties authentication.

Right now, when a user sign-up with email&password, the server generates a JWT associated to that user.

function createToken(user, role) {
    var usr = {
        role: role,      // admin | customer | shop
        email: user.email,
        name: user.name
    };

    var expires = (Date.now() / 1000) + 60 * 60 * 24 * 365; // 1 year
    var nbf = Date.now() / 1000;
    usr['nbf'] = nbf;
    usr['exp'] = expires;
    var token = jwts.encode(usr, process.env.SECRET);
    return token;
}

When the Web-Client receives that token, it stores the token in cookie/web_storage, and uses it for every API call to the server, and for the auto-log-in as well. The token contains also the role , so when server receives a request, it knows if that user/role can access to the route/resource asked.

function checkToken(token, api_name) {
    // verifies secret and checks exp
    jwt.verify(token, process.env.SECRET,
        function (err, decoded) {
            if (err) { throw { msg: "token expired or not authenticated", code: errors.ERR_NOT_AUTH }; }
            else {
                var role = decoded['role'];
                return does_role_can_access_api(role, api_name); // true or false             
            }
    });
}

Now some 3rd parties want to access to some of my APIs. I want to create an Express-Gateway to make api-keys for applications that wants to use my server, and keep existing JWT authentication for single users.

So I will have

 |----------------|
 |   my Web-App   |
 |----------------|----> |------------|            |------------|
                         |   Express  |            | my Server  |
                         |   Gateway  |----------> |    APIs    |
 |----------------|----> |------------|            |------------|
 |    3rd party   |
 |----------------|
  • My Web-App, should access to all the APIs, because my Web-App is used by admin s (like me), and by our users ( customers and shops ).
  • 3rd party Apps, should access only to some APIs, since they will be only customers and shops .

So I want to make something like this:

 |----------------|
 |   my Web-App   |
 |     scopes:    |
 | [admin, user]  |
 |                |
 |----------------|----> |------------|            |------------|
                         |   Express  |            | my Server  |
                         |   Gateway  |----------> |    APIs    |
 |----------------|----> |------------|            |------------|
 |    3rd party   |
 |    scopes:     |
 |     [user]     |
 |----------------|

At the end, my Web-App will have an ApiKey with all the scopes, while 3rd parties ApiKeys will have just user scope, so I can filter routes on that. Single real users, regardless to the App used, will use the JWT token to log-in and make requests.

So every request will have an ApiKey (based on the Application used) and a JWT Token (to identify the user):

  • The ApiKey will be added to the header by the 3rd party server,
  • The JWT Token will be (retrieved and) added to the header by the web_storage of the User's Browser.

Does it sound good?

First of wall congratulations for all your efforts in developing a secure application, because it's not every day we see developers going that far.

Clarifying Possible Misconceptions

Before I dive into your question I would like to first clear a misconception that usually developers carry around regarding what vs who is accessing their backends. This is discussed in detail in this article , where we can read:

The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?

The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.

While the article is in the context of a mobile app, for understanding the difference between what and who is accessing the API server, the references to mobile app can be replaced with web app . If you steal have doubts please go and read the section of the linked article, that also includes a graphic to help with understanding this.

Your Question

Right now, when a user sign-up with email&password, the server generates a JWT associated to that user.

 var expires = (Date.now() / 1000) + 60 * 60 * 24 * 365; // 1 year

My Web-App, should access to all the APIs, because my Web-App is used by admins (like me), and by our users (customers and shops).

This is way to long for an Authentication token, specially when you say that the API is accessed by admins, but even for normal users is too long.

Depending on your use case I recommend them to be in the minutes range, thus I suggest you to switch to use refresh tokens, that will keep the access tokens short lived while refresh tokens can be long lived, but in the hours range, not days, weeks or years.

Refresh Token flow example:

缩短令牌寿命的图形

Sourced from: Mobile API Security Techniques - part 2

NOTE : While the above graphic belongs to a series of articles written in the context of mobile APIs, they have a lot of information that is also valid for APIs serving web apps and third party clients.

By using this approach, the client on failure of the short lived access token will need to request a new one by sending a refresh token in order to get a new access token.

The important bit here is that the refresh token should not be sent to the browser, only the access token can be sent, therefore your third party clients must be very aware of that, so that will not try to access your API directly from javascript, instead they should delegate that to their backends.

API Keys and JWT's

At the end, my Web-App will have an ApiKey with all the scopes, while 3rd parties ApiKeys will have just user scope, so I can filter routes on that. Single real users, regardless to the App used, will use the JWT token to log-in and make requests. So every request will have an ApiKey (based on the Application used) and a JWT Token (to identify the user):

The ApiKey will be added to the header by the 3rd party server, The JWT Token will be (retrieved and) added to the header by the web_storage of the User's Browser.

I am not sure if you are saying that the API key will be also the JWT token, but if not, then I would also use the the JWT token as the API key, but with a scope/role specific to each of your third party clients.

Going the Extra Mile

I don't resist to include in any security question I answer the excellent work done by the OWASP foundation, and this case the most relevant to you is the Web Security Testing Guide :

The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM