简体   繁体   English

使用 Express-Gateway 访问 Api 和使用 JWT 进行用户身份验证的建议

[英]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.我在 Express 中有一个服务器,它向 Web 应用程序公开了一些 API。 I am looking for a good way to manage both final users and 3rd parties authentication.我正在寻找一种管理最终用户和 3rd 方身份验证的好方法。

Right now, when a user sign-up with email&password, the server generates a JWT associated to that user.现在,当用户使用电子邮件和密码注册时,服务器会生成与该用户关联的 JWT。

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.当 Web 客户端收到该令牌时,它会将令牌存储在 cookie/web_storage 中,并将其用于对服务器的每个 API 调用以及自动登录。 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.令牌还包含role ,因此当服务器收到请求时,它知道该用户/角色是否可以访问请求的路由/资源。

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.现在一些 3rd 方想要访问我的一些API。 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.我想创建一个 Express-Gateway 来为想要使用我的服务器的应用程序制作 api 密钥,并为单个用户保留现有的 JWT 身份验证。

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 ).我的 Web 应用程序应该访问所有 API,因为我的 Web 应用程序由admin (像我一样)和我们的用户( customersshops )使用。
  • 3rd party Apps, should access only to some APIs, since they will be only customers and shops .第 3 方应用程序,应仅访问某些 API,因为它们将仅是customersshops

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.最后,我的 Web 应用程序将有一个包含所有范围的 ApiKey,而第 3 方 ApiKeys 将只有user范围,所以我可以过滤路由。 Single real users, regardless to the App used, will use the JWT token to log-in and make requests.单个真实用户,无论使用何种 App,都将使用 JWT 令牌登录并发出请求。

So every request will have an ApiKey (based on the Application used) and a JWT Token (to identify the user):所以每个请求都会有一个 ApiKey(基于所使用的应用程序)和一个 JWT 令牌(用于识别用户):

  • The ApiKey will be added to the header by the 3rd party server, ApiKey 将由 3rd 方服务器添加到标头中,
  • The JWT Token will be (retrieved and) added to the header by the web_storage of the User's Browser. JWT 令牌将由用户浏览器的 web_storage(检索和)添加到标头中。

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.我潜入你的问题之前,我想先明确一个误解,认为一般的开发人员随身携带关于什么VS在访问他们的后端。 This is discussed in detail in this article , where we can read:这在详细讨论这篇文章,在这里我们可以读到:

The what is the thing making the request to the API server.向 API 服务器发出请求的内容什么 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?它真的是您的移动应用程序的真实实例,还是机器人、自动化脚本或攻击者使用 Postman 之类的工具手动浏览您的 API 服务器?

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.是移动应用,我们可以验证,授权和以多种方式确定,比如使用OpenID登录连接或流的oauth2的用户。

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 .虽然本文是在移动应用程序的上下文中,但为了了解访问 API 服务器的内容人员之间的区别,对mobile app的引用可以替换为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.现在,当用户使用电子邮件和密码注册时,服务器会生成与该用户关联的 JWT。

 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).我的 Web 应用程序应该访问所有 API,因为我的 Web 应用程序由管理员(如我)和我们的用户(客户和商店)使用。

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.这是渴望身份验证令牌的方式,特别是当您说该 API 由管理员访问时,但即使对于普通用户来说也太长了。

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 来源:移动 API 安全技术 - 第 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.注意:虽然上图属于在移动 API 上下文中编写的一系列文章,但它们有很多信息也适用于为 Web 应用程序和第三方客户端提供服务的 API。

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.这里重要的一点是刷新令牌不应发送到浏览器,只能发送访问令牌,因此您的第三方客户端必须非常清楚这一点,以免尝试直接从 javascript 访问您的 API,相反,他们应该将其委托给他们的后端。

API Keys and JWT's API 密钥和 JWT

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.最后,我的 Web 应用程序将有一个包含所有范围的 ApiKey,而第 3 方 ApiKeys 将只有用户范围,所以我可以过滤路由。 Single real users, regardless to the App used, will use the JWT token to log-in and make requests.单个真实用户,无论使用何种 App,都将使用 JWT 令牌登录并发出请求。 So every request will have an ApiKey (based on the Application used) and a JWT Token (to identify the user):所以每个请求都会有一个 ApiKey(基于所使用的应用程序)和一个 JWT 令牌(用于识别用户):

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. ApiKey 将由第 3 方服务器添加到标头中,JWT 令牌将通过用户浏览器的 web_storage(检索和)添加到标头中。

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.我不确定您是否说 API 密钥也是 JWT 令牌,但如果不是,那么我也会使用 JWT 令牌作为 API 密钥,但具有特定于每个第三方的范围/角色客户。

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 :我不抗拒在任何安全问题中包含我回答 OWASP 基金会所做的出色工作,与您最相关的案例是Web 安全测试指南

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. OWASP Web 安全测试指南包括一个“最佳实践”渗透测试框架,用户可以在他们自己的组织中实施该框架和一个“低级”渗透测试指南,它描述了测试最常见的 Web 应用程序和 Web 服务安全问题的技术。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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