Laravel Passport授权码模式下如何校验第三方客户端scope申请合法性
适配运行环境
- 本次权限机制验证的对应环境配置
- Passport 版本:10.1.3
- Laravel 版本:6.20.16
- PHP 版本:7.4.14
- 数据库驱动及版本:10.5.8-MariaDB
- 流程基础:项目采用授权码许可令牌(Authorization Code Grant Token)流程
Passport Scope 校验的核心底层逻辑
Passport对scope的校验是分两个服务端节点做的全链路拦截,从机制上杜绝客户端谎报权限范围的可能,全程不会直接信任客户端传递的scope参数:
- 授权页跳转阶段的前置校验
当第三方客户端携带申请的scope参数,把用户引导到平台的授权确认页时,服务端会立刻完成两层校验:- 先逐字检查客户端携带的所有scope是否属于平台预先注册定义的合法scope,拦截随机编造的无效字符串
- 再从数据库读取当前客户端(通过
client_id匹配对应客户端记录)预先配置的可使用scope集合,和本次申请的scope做全量匹配
- 令牌签发阶段的二次校验
等用户在授权页确认权限、后端通过授权码交换访问令牌时,会再次从数据库读取当前客户端最新的scope授权配置,对所有要写到令牌上的scope做最后一次合法性校验,不在授权范围内的scope会直接被剔除或触发异常。
典型场景的实际校验表现
场景1:客户端被收回部分scope权限
- 平台后台收回客户端的部分scope授权,本质是直接修改数据库中存储的客户端-scope绑定关系配置
- 后续如果客户端申请令牌时仍然携带被收回的3个scope,在授权页前置校验环节就会匹配失败:要么直接拦截跳转抛出授权错误,要么自动从申请列表剔除无权限的scope,仅给用户展示当前客户端合法可用的范围供确认
- 哪怕有人绕过前端流程,在交换令牌的请求里手动把被收回的scope参数加进去,服务端读取的是最新的数据库授权配置,发现不在合法列表内就会直接抛出标准OAuth
invalid_scope错误,不会签发带越权scope的令牌
场景2:客户端冒用其他客户端的专属scope
- Passport的scope授权是按客户端维度独立存储的,每个客户端的可使用scope集合是独立映射的,不存在跨客户端自动共享的权限
- 第二个客户端如果携带第一个客户端的专属scope发起申请,因为这个scope根本不在自身的授权列表里,在授权页前置校验环节就会被拦截
- 哪怕使用第二个客户端的合法凭证直接调用令牌接口申请越权scope,后端从数据库读取的该客户端合法scope列表里没有对应条目,会直接拦截请求返回权限错误,不会放行
容易忽略的实现细节
- 原生Passport 10.x版本的scope校验逻辑,是内置在
ValidateScope中间件、授权码生成与令牌签发的核心流程里的,全程使用数据库存储的权威授权配置做比对,不会把客户端传的scope参数原封不动写入访问令牌 - 只有当项目自定义scope校验逻辑、主动跳过默认的客户端scope匹配环节时,才会出现越权申请scope的风险,框架默认逻辑不存在这个安全漏洞
内容的提问来源于stack exchange,提问作者enaeim
相关产品推荐
相关产品推荐

