Laravel 5.6-自耗API的Passport JWT httponly cookie SPA身份验证? [英] Laravel 5.6 - Passport JWT httponly cookie SPA authentication for self consuming API?

查看:108
本文介绍了Laravel 5.6-自耗API的Passport JWT httponly cookie SPA身份验证?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:我在这个问题上有4个赏金,但是以下未获好评的答案都不是该问题所需的答案.所需的一切都在下面的Update 3中,只需查找要实现的Laravel代码即可.

更新3:此流程图完全是我要完成的流程,下面的所有内容都是原始问题,其中包含一些较旧的更新.该流程图总结了所需的一切.

下面流程图中的绿色部分是我知道该怎么做的部分.红色部分及其旁注是我在寻求使用Laravel代码完成操作时所寻求的帮助.

The green parts in the flow chart below are the parts that I know how to do. The red parts along with their side notes is what I am looking for help accomplishing using Laravel code.

我已经做了大量研究,但是在将Laravel与JWT httponly cookie用于自用API时,信息总是简短而不完整(大多数在线教程仅显示JWT存储在本地存储中,即不太安全).看起来,当通过向服务器发送的每个请求来验证用户身份时,应该使用包含Passport的JWT的httponly cookie来识别Javascript端的用户.

I have done a lot of research but the information always ended up short and not complete when it comes to using Laravel with a JWT httponly cookie for a self consuming API (most tutorials online only show JWT being stored in local storage which is not very secure). It looks like httponly cookie containing a JWT by Passport should be used to identify the user on the Javascript side when sent with every request to the server to validate that the user is who they say they are.

要了解如何使此设置有效的完整图片,还需要做一些其他事情,而在涵盖该内容的单个教程中没有见过:

There are also some additional things that are needed to have a complete picture of how to make this setup work which I haven't come across in a single tutorial which covers this:

    从Google端登录后,
  1. Laravel Passport(不是tymon auth)可以生成加密的JWT,并将其作为httponly cookie发送为响应.使用什么中间件?如果刷新令牌增加了安全性,如何实现?
  2. 用于调用auth端点的JavaScript(例如,axios)api伪代码,如何将httponly cookie传递给后端,以及后端如何验证令牌有效.
  3. 如果单个帐户是从多个设备登录的,那么一台设备被盗了,如何撤消所有已认证用户设备的访问权限(假设用户从他们可以控制的登录设备上更改密码)?
  4. 登录/注册,注销,更改密码,忘记密码控制器方法通常看起来像什么来处理令牌的创建/验证/吊销?
  5. CSRF令牌集成.
  1. Laravel Passport (not tymon auth) to generate encrypted JWT and send it as httponly cookie as response after login from JS side. What middleware to use? If refresh tokens add more security, how to implement?
  2. JavaScript (axios for example) api pseudo code that makes call to auth endpoint, how is httponly cookie passed to backend, and how does backend verify token is valid.
  3. If single account is logged in from multiple devices, then a device is stolen, how to revoke access from all the authed user devices (assuming user does Change Password from a logged in device they have control over)?
  4. What would Login/Register, Logout, Change Password, Forgot Password controller methods typically look like to handle the creation/validating/revoking of tokens?
  5. CSRF token integration.

我希望这个问题的答案能为将来的读者和那些目前正在努力寻找可解决上述问题的读者提供一个容易遵循的指南.

I hope an answer to this question serves as an easy to follow guide for future readers and those struggling at the moment to find an answer covering the above points on a self consuming API.

更新1:

  1. 请注意,我之前曾尝试过CreateFreshApiToken,但是在撤销用户令牌时(对于上述第3点和第4点),该方法不起作用.这是基于核心laravel开发人员在谈论时此评论 CreateFreshApiToken中间件:
  1. Please note I tried the CreateFreshApiToken before, but that didn't work when it comes to revoking tokens of the user (for points 3 and 4 above). This is based on this comment by a core laravel developer, when talking about the CreateFreshApiToken middleware:

此中间件创建的JWT令牌不会存储在任何地方.他们 无法撤销或不存在".它们只是为您提供了一种方法 通过laravel_token cookie进行身份验证的api调用.不是 与访问令牌有关. 另外:通常,您不会在发行它们的同一应用程序上使用客户端发行的令牌.您可以在第一方或第三方中使用它们 应用程序.使用中间件或客户端发行的令牌,但不使用 两者都在同一时间.

JWT tokens created by this middleware aren't stored anywhere. They can't be revoked or "not exist". They simply provide a way for your api calls to be authed through the laravel_token cookie. It isn't related to access tokens. Also: you normally wouldn't use tokens issued by clients on the same app which issues them. You'd use them in a first or third party app. Either use the middleware or the client issued tokens but not both at the same time.

因此,似乎可以满足第3点和第4点的要求,以撤消令牌,如果使用CreateFreshApiToken中间件,则不可能这样做.

So it seems to be able to cater to points 3 and 4 to revoke tokens, it's not possible to do so if using the CreateFreshApiToken middleware.

  1. 在客户端,处理安全的httpOnly cookie似乎不是Authorization: Bearer <token>的方法.我认为请求/响应应该包括安全的httpOnly cookie作为请求/响应标头,例如,基于laravel文档:
  1. On the client side, it seems Authorization: Bearer <token> is not the way to go when dealing with the secure httpOnly cookie. I think the request/response are supposed to include the secure httpOnly cookie as a request/response header, like this based on the laravel docs:

使用此身份验证方法时,默认为Laravel JavaScript支架指示Axios始终发送X-CSRF-TOKEN 和X-Requested-With标头.

When using this method of authentication, the default Laravel JavaScript scaffolding instructs Axios to always send the X-CSRF-TOKEN and X-Requested-With headers.

headerswindow.axios.defaults.headers.common = {
    'X-Requested-With': 'XMLHttpRequest',
    'X-CSRF-TOKEN': (csrf_token goes here)
};

这也是我正在寻找一个涵盖以上所有要点的解决方案的原因.抱歉,我使用的是Laravel 5.6,而不是5.5.

This is also the reason I am looking for a solution which covers all the points above. Apologies, I am using Laravel 5.6 not 5.5.

更新2:

密码授予/刷新令牌授予组合似乎是必经之路.使用 Password Grant/Refresh Token Grant 组合查找易于遵循的实施指南.

It seems the Password Grant/Refresh Token Grant combo is the way to go. Looking for an easy to follow implementation guide using Password Grant/Refresh Token Grant combo.

密码授予: 此赠款适合与我们信任的客户打交道, 就像我们自己网站的移动应用一样.在这种情况下,客户端发送 用户登录授权服务器的凭据以及 服务器直接颁发访问令牌.

Password Grant: This grant is suitable when dealing with the client that we trust, like a mobile app for our own website. In this case, the client sends the user's login credentials to the authorization server and the server directly issues the access token.

刷新令牌授予: 当服务器发出访问令牌时,它还会为 访问令牌.当我们想要刷新令牌时使用刷新令牌授予 过期后访问令牌.在这种情况下,授权服务器 将在发出访问令牌时发送刷新令牌,该令牌可以是 用于请求新的访问令牌.

Refresh Token Grant: When the server issues an access token, it also sets an expiry for the access token. Refresh token grant is used when we want to refresh the access token once it is expired. In this case, authorization server will send a refresh token while issuing the access token, which can be used to request a new access token.

我正在寻找一个使用密码授予/刷新令牌授予组合的简便,直接,全面的答案,该组合使用httpOnly安全cookie覆盖上述原始5点的所有部分, /revoking/refreshing令牌,创建登录cookie,注销注销cookie,控制器方法,CSRF等.

I am looking for an easy to implement, straight forward, holistic answer using the Password Grant/Refresh Token Grant combo that covers all the parts of the above original 5 points with httpOnly secure cookie, creating/revoking/refreshing tokens, login cookie creation, logout cookie revoking, controller methods, CSRF, etc.

推荐答案

Laravel Passport JWT

Laravel Passport JWT

  1. 要使用此功能,您需要禁用cookie序列化. Laravel 5.5在cookie值的序列化/反序列化方面存在问题. 您可以在此处了解更多信息( https://laravel.com/docs/5.5/upgrade)

  1. To use this feature you need to disable cookie serialization. Laravel 5.5 has an issue with serialization / unserialization of cookie values. You can read more about this here (https://laravel.com/docs/5.5/upgrade)

请确保

  • 您的刀片模板头中有<meta name="csrf-token" content="{{ csrf_token() }}">

axios设置为对每个请求使用csrf_token.

axios is set to use csrf_token on each request.

您应该在resources/assets/js/bootstrap.js

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
  window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
  console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

  1. 此处说明设置身份验证路由( https://laravel.com/docs/5.5/authentication)
  2. 此处说明设置护照( https://laravel.com/docs/5.5/passport).
  1. Setup auth routes explained here (https://laravel.com/docs/5.5/authentication)
  2. Setup passport explained here (https://laravel.com/docs/5.5/passport).

重要的部分是:

  • Laravel\Passport\HasApiTokens特征添加到您的User模型
  • config/auth.php
  • 中将api身份验证保护的driver选项设置为passport
  • \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,中间件添加到app/Http/Kernel.php
  • 中的web中间件组中
  • add the Laravel\Passport\HasApiTokens trait to your User model
  • set the driver option of the api authentication guard to passport in your config/auth.php
  • add the \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class, middleware to your web middleware group in app/Http/Kernel.php

请注意,您可能可以跳过迁移并创建客户端.

Note you probably can skip migrations and creating clients.

  1. /login发出POST请求,以传递您的凭据.您可以提出AJAX请求或普通表单提交.
  1. Make a POST request to /login passing your credentials. You can make an AJAX request or normal form submit.

如果登录请求是AJAX(使用axios),则响应数据将是HTML,但是您感兴趣的是状态码.

If the login request is AJAX (using axios) the response data will be the HTML but what are you interested at is the status code.

axios.get(
  '/login, 
  {
    email: 'user@email.com',
    password: 'secret',
  },
  {
    headers: {
      'Accept': 'application/json', // set this header to get json validation errors.
    },
  },
).then(response => {
  if (response.status === 200) {
      // the cookie was set in browser
      // the response.data will be HTML string but I don't think you are interested in that
    }
    // do something in this case
}).catch(error => {
  if (error.response.status === 422) {
    // error.response.data is an object containing validation errors
  }
  // do something in this case
});

登录时,服务器通过提供的凭据查找用户,并根据用户信息(ID,电子邮件...)生成令牌(此令牌未保存在任何地方) 然后服务器返回带有包含生成的令牌的加密cookie的响应.

On login, the server finds the user by credentials provided, generates a token based on user info (id, email ...) (this token is not saved anywhere) then the server returns a response with an encrypted cookie that contains the generated token.

  1. 对受保护的路由进行API调用.

假设您的路由受保护

Route::get('protected', 'SomeController@protected')->middleware('auth:api');

您可以像往常一样使用axios进行ajax调用. Cookie会自动设置.

You can make an ajax call using axios as normal. The cookies are automatically set.

axios.get('/api/protected')
  .then(response => {
    // do something with the response
  }).catch(error => {
    // do something with this case of error
  });

当服务器收到呼叫时,解密请求laravel_cookie并获取用户信息(例如:id,email ...) 然后使用该用户信息进行数据库查找,以检查该用户是否存在. 如果找到用户,则授权该用户访问所请求的资源. 否则返回401.

When the server receives the call decrypts the request laravel_cookie and get user information (ex: id, email ...) Then with that user info does a database lookup to check if the user exists. If the user is found then the user is authorized to access the requested resource. Else a 401 is returned.

使JWT令牌无效.正如您提到的评论,无需担心这一点,因为此令牌未保存在服务器上的任何位置.

Invalidating the JWT token. As you mention the comment there's no need to worry about this since this token is not saved anywhere on the server.

关于第3点,Laravel 5.6 Auth具有新的方法logoutOtherDevices.您可以从此处了解更多信息( https://laracasts .com/series/whats-new-in-laravel-5-6/episodes/7 ) 因为文档非常简短.

Regarding point 3 Laravel 5.6 Auth has a new method logoutOtherDevices. You can learn more from here (https://laracasts.com/series/whats-new-in-laravel-5-6/episodes/7) since the documentation is very light.

如果您无法更新Laravel版本,则可以查看5.6中的操作,并为5.5构建自己的实现.

If you can't update your Laravel version you can check it out how is done in 5.6 and build your own implementation for 5.5

问题第4点.看一下app/Http/Controllers/Auth中找到的控制器.

Point 4 from your question. Take a look at controllers found in app/Http/Controllers/Auth.

关于access_tokens和refresh_tokens,这是一种完全不同且更复杂的方法. 您可以在网上找到许多说明方法的教程.

Regarding access_tokens and refresh_tokens this is a totally different and more complex approach. You can find lots of tutorials online explaining how to do it.

希望对您有帮助.

PS.祝新年快乐!! :)

PS. Have a Happy New Year!! :)

这篇关于Laravel 5.6-自耗API的Passport JWT httponly cookie SPA身份验证?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆