我想构建一个带有(Asp.Net Core(后端的(Angular(SPA,我想使用安全最佳实践。我的计划是这样的:
- SPA 显示"登录"按钮
- 单击"登录"按钮会启动与某个身份提供商(Google、Microsoft等(的授权代码openid-connect流程。
- 用户使用身份提供程序进行身份验证,然后使用授权代码重定向回 SPA
- 然后,SPA 向后端发出登录请求并传递授权代码
- 后端向身份提供程序发出请求,将代码交换为id_token,并为用户创建某种会话票证
现在这就是我因缺乏正确理解而陷入困境的地方
问题 1 - 最佳实践
上述程序甚至被认为是最佳实践吗?还是我做错了?
问题 2 - 身份验证票证
我的后端只有API,它不为用户呈现HTML页面,只提供Json响应。我应该创建哪种类型的身份验证票证?它应该是 JWT 还是 Cookie?我认为它不可能是 cookie,因为 API 无法返回浏览器将正确存储的 cookie。所以它必须是某种令牌,最好是 JWT。SPA应该如何存储它,本地/会话存储?
问题 3 - 过期和刷新
假设后端向 SPA 返回 JWT,则此 JWT 应包含什么?它的到期时间应该是多少?我应该如何处理自动刷新?
问题 4 - 必需的包和库
此外,特定于编程(因为这毕竟是一个编程问题(,所有这些需要什么库。这个问题既针对 SPA,也针对后端。我假设我需要某种SPA 的 openid-connect客户端,并且我需要后端上的一些库来完成授权代码流(交换id_token的代码(这是由IdentityServer4
完成的吗?还是有其他库。
更新
我准备了一个解决方案,致力于展示做所有事情的正确方法。这是一项正在进行的工作,凌乱且不干净,但它是最小的,它有效并努力遵循最佳实践。
https://github.com/paviad/dotnet-angular-fullstack
OpenID Connect
是一个标准(在OAuth 2.0之上(,它有很多流(你提到了一个Authorization Code flow
,这对于SPA来说不是最好的。
建议对 SPA 应用程序进行Implicit flow
,其中 SPA 直接从 IdP 接收令牌。隐式流现已弃用,Authorization Code with PKCE Flow
是目前 SPA 的最佳选择。这篇随机博客文章将为您提供有关这些流程的更多详细信息。
SPA 可能还会接收刷新令牌,该令牌可用于获取新的访问令牌,但这取决于使用的 IdP。
后端只需要库来验证令牌(从请求Authorization
标头(,最终它需要验证一些声明(例如角色(以获得可选授权。它不需要处理任何 OIDC 流,因为它通常通过响应代码(200、401、403、500 等(通信回 SPA,SPA 处理错误。
恕我直言,只需为您的 SPA 选择合适的库(更喜欢 OIDC 认证((我最喜欢的 Angular(,它将提供许多开箱即用的有用 SPA 功能(正确的流程、令牌刷新、令牌存储、用于后端调用的 http 拦截器......我会避免任何 IdP 提供的库 - 它可以快速实现,但如果它们提供 OIDC 标准之外的某些功能,则可能是 IdP 供应商锁定。