To summarize your situation: You have your own backend (server of some kind, such as a web application implementing a REST API) where users should be able to login using a username and password to obtain an access token giving their access to their own resources on the server, and they should be able to do this through your own frontend (client of some kind, such as smartphone app, desktop app, single-page application, etc.). The Resource Owner Password Grant solved your problem perfectly fine, but now it got deprecated :(
总结您的情况:您有自己的后端(某种类型的服务器,例如实现REST API的Web应用程序),用户应该能够使用用户名和密码登录,以获得访问令牌,从而访问他们在服务器上的自己的资源,并且他们应该能够通过您自己的前端(某种类型的客户端,如智能手机应用程序、桌面应用程序、单页面应用程序等)来完成这项工作。资源所有者密码授予很好地解决了您的问题,但现在它被弃用了:(
Note
It says in the OAuth 2.0 spec that The OAuth 2.0 authorization framework enables a third-party application to obtain limited access [...]. Your frontend is not really a third-party application in this case, but a first-party application, so you shouldn't really use OAuth 2.0, but it's better to use something well-documented instead of inventing your own solution to handle authorization, so just as you, I would still use OAuth 2.0.
注意OAuth 2.0规范中说,OAuth 2.0授权框架允许第三方应用程序获得有限的访问权限[...]。在这种情况下,你的前端并不是真正的第三方应用程序,而是第一方应用程序,所以你不应该真正使用OAuth 2.0,但最好使用一些有良好文档的东西,而不是发明自己的解决方案来处理授权,所以就像你一样,我仍然会使用OAuth 2.0。
Simple solution (deprecated)
Continue using Resource Owner Password Grant. It does precisely what you want, and it was created for your specific case (frontend and backend come from the same "company").
简单解决方案(已弃用)继续使用资源所有者密码授予。它做的正是您想要的,而且它是为您的特定案例创建的(前端和后端来自同一个“公司”)。
Now they seem to have decided that OAuth 2.1 should not support first-party applications like this, but I would say it's still fine to use it for your case. It would be much worse if Google or someone else big OAuth 2.0 provider would support this Grant Type, because then developers might create their own frontend applications and let users login in on their frontend application by entering their Google username and password directly into the frontend application, i.e. revealing their Google credentials to the frontend developer. I imagine the reason they deprecate this Grant Type is to avoid such situations.
现在他们似乎已经决定OAuth 2.1不应该支持这样的第一方应用程序,但我想说,在您的情况下使用它仍然是很好的。如果Google或其他大型OAuth 2.0提供商支持这种Grant Type,情况会更糟,因为然后开发人员可能会创建他们自己的前端应用程序,并让用户通过直接在前端应用程序中输入他们的Google用户名和密码来登录他们的前端应用程序,即向前端开发人员展示他们的Google凭据。我想他们反对这种Grant类型的原因是为了避免这种情况。
Better solution (deprecated)
Use Implicit Grant. In the frontend, when the user wants to login, redirect the user to the backend (i.e. open a webpage on the backend with a login form where the user can enter username and password), and after the user has successfully logged in on the backend, redirect the client back to the frontend with the access token. The benefit here is that the user only reveals her password to the backend application, and never to any client application. The drawback is that the backend must contain a webpage for the login form, making it a bit more complicated to implement compared to a pure REST API. And if you want to do this properly, the server should have a list of pre-registered clients with ids and secrets, but if you only have your own frontend you need to support I would say you can skip that or simply hardcode a client id in the backend application.
更好的解决方案(已弃用)使用隐式授予。在前端,当用户想要登录时,将用户重定向到后台(即在后台打开一个网页,其中有一个登录表单,用户可以输入用户名和密码),当用户成功登录到后台后,使用访问令牌将客户端重定向回前端。这里的好处是,用户只向后端应用程序透露其密码,而不会向任何客户端应用程序透露。缺点是后端必须包含登录表单的网页,与纯REST API相比,这使得它的实现稍微复杂一些。如果你想正确地做到这一点,服务器应该有一个预先注册的带有ID和机密的客户端列表,但如果你只有你自己的前端,你需要支持,我会说你可以跳过这一点,或者简单地在后端应用程序中硬编码客户端ID。
Unfortunately, this grant type has been deprecated as well...
不幸的是,这种赠款类型也已被弃用。
Proper solution
Use Authorization Code Grant (with Proof Key for Code Exchange). This way is really similar to the Implicit Grant described above, but instead of redirecting the user back to the frontend with the Access Token, you redirect the user back to the frontend with an Authorization Code. The frontend can then send this Authorization Code to the backend and get back the Access Token.
正确的解决方案使用授权码授予(带有代码交换的证明密钥)。这种方式实际上类似于上面描述的隐式Grant,但不是使用访问令牌将用户重定向回前端,而是使用授权码将用户重定向回前端。然后,前端可以将该授权码发送到后端,并取回访问令牌。
What was described above was more or less only Authorization Code Grant. "with Proof Key for Code Exchange" is pretty much the same, but you also use a "key" to prove that you are the same client that redirects that user to the backend as and that trades the Authorization Code for an Access Token (the "with Proof Key for Code Exchange" part basically makes it more secure).
上面所描述的或多或少只是授权码授予。“用于代码交换的带证明密钥”基本相同,但您还可以使用“密钥”来证明您是将该用户重定向到后端并用授权码交换访问令牌的同一个客户端(“用于代码交换的带证明密钥”部分基本上使其更安全)。
Here I've of course only described the overall idea, you need to look into the specifications to learn the details about the requests and responses you should send (what the body of the request should be, what status codes that are used, etc.).
当然,我在这里只描述了总体思想,您需要查看规范以了解有关您应该发送的请求和响应的细节(请求的正文应该是什么,使用了什么状态代码,等等)。
OAuth is specifically designed for delegated authorization, that is, authorization to access a resource on behalf of the user.
It is not designed for authentication. OpenID Connect (built-on top of OAuth) is designed for authentication.
OAuth是专门为委托授权设计的,即代表用户访问资源的授权。它不是为身份验证而设计的。OpenID Connect(内置在OAuth之上)用于身份验证。
In a delegated authentication/authorization environment, the authentication/authorization tasks are performed by specific independent services. If your application also manages authentication/authorization, maybe you don't need OpenID Connect/OAuth.
在委托的身份验证/授权环境中,身份验证/授权任务由特定的独立服务执行。如果您的应用程序还管理身份验证/授权,则可能不需要OpenID Connect/OAuth。
Anyway, the Resource Owner Password Grant is the worst delegated OAuth flow. It should be used in very rare legacy cases, and it is deprecated in OAuth2.1.
See this article for more details.
无论如何,资源所有者密码授予是最糟糕的委托OAuth流。它应该在非常罕见的遗留情况下使用,在OAuth2.1中已弃用。有关更多详细信息,请参阅本文。
The OAuth flow to use mostly depends on your application architecture.
Take a look here to determine which flow better fits your needs.
要使用的OAuth流主要取决于您的应用程序架构。请看这里,以确定哪种流程更适合您的需求。
更多回答
Hello Peppe, I implemented PKCE flow successfully however facing an issue. Flow works fine on the first iteration however when user logs out and tries logging back in, auth server doesn't show up the login page and straight away issues new JWT token. Looks like auth server stores the session of the user somewhere. Both client and auth server belongs to me. Just to be clear, here is the flow. Click Login > verifier & challenge generated > Auth server gives Login Form > Tom enters credentials > Token issued > log out Click Login > verifier & challenge generated > Token issued > log out
您好佩佩,我成功地实施了PKCE流程,但面临一个问题。Flow在第一次迭代中运行良好,但是当用户注销并尝试重新登录时,auth服务器不会显示登录页面,并立即发出新的JWT令牌。看起来身份验证服务器将用户的会话存储在某个地方。客户端和身份验证服务器都属于我。我只想说清楚,以下是流程。单击登录>验证器和生成的质询>身份验证服务器提供的登录表单>Tom输入凭据>令牌颁发>注销单击登录>验证者和质询生成>令牌颁发>注销
Problem with this is, on the 2nd iteration, I can not login as a different user. On the logout I am invalidating the session and deleting the cookies as well .. here is the code snippet --> (.logout() .invalidateHttpSession(true) .deleteCookies("JSESSIONID")) .permitAll() .and()
问题是,在第二次迭代时,我无法以其他用户身份登录。在注销时,我将使会话无效并同时删除Cookie。以下是代码片段-->(.logout().invaliateHttpSession(True).deleteCookies(“jessionid”)).permitAll().and()
@Sachin You seem to have a very specific problem related to the OAuth 2.0 server you're using. It is more suitable that you to create a new question here on Stack Overflow where you describe the problem and provide more details on the OAuth 2.0 server.
@Sachin您似乎遇到了与您正在使用的OAuth 2.0服务器有关的非常具体的问题。更适合您在这里创建一个关于Stack Overflow的新问题,其中您描述了问题并提供了有关OAuth 2.0服务器的更多细节。
@Sachin Sorry, I have no experience of using Spring Authorization server 1.0, so I'm afraid I can't help you.
@Sachin对不起,我没有使用Spring Authorization SERVER 1.0的经验,恐怕帮不了您。
我是一名优秀的程序员,十分优秀!