Scope
Scope 是你请求用户授予的权限。Nanako 有四个,而它们全部只影响一件事:
/oauth/userinfo 返回哪些 claim。
四个 scope
| Scope | 授予什么 | 在 /oauth/userinfo 里增加的 claim |
|---|---|---|
openid | 单独使用时什么都不授予 | — |
profile | 昵称与头像 | name、picture |
email | 邮箱地址 | email、email_verified |
phone | 手机号 | phone_number、phone_number_verified |
sub 永远返回,与 scope 无关。除它之外的每个 claim 都需要对应的 scope。
底层值为空时,claim 是直接不出现,而不是返回 null。一个没填手机号的用户,即使
令牌带着 phone,响应里也完全没有 phone_number 这个键。读取时请做好防御。
关于 openid
openid 不解锁任何数据。Nanako 接受它,是因为 OIDC 客户端库默认会发这个 scope,
而且它出现在请求的默认值里 —— 但没有任何逻辑依赖它。
你并不需要它。而且如果你的应用是通过网页表单注册的,它几乎肯定不在允许集合里 —— 见每次都显式传 scope。
申请 scope
Scope 在 scope 参数里用空格分隔:
&scope=profile%20email
按最小必要申请。每多一个 scope,授权页上就多一行,用户就多一个犹豫的理由。
格式要求很严。取值按单个空格切分,每一段都必须是已知 scope,所以连续两个空格、 开头空格或结尾空格都会切出一个空串并导致请求失败:
{"error": "invalid_scope", "error_description": "scope '' 不被允许"}
scope 是怎么校验的
你的应用有一个允许集合,注册时确定,可在开发者页面修改。授权请求会与它比对:
只要有任何一个请求的 scope 不在集合内,请求就以 invalid_scope 被拒绝,用户什么
都看不到。
请求的 scope ── 是允许集合的子集? ──► 授权页 ──► 实际授予的 scope
│
└── 否 ──► 400 invalid_scope
实际授予的 scope 会出现在 token 响应里,也是 access token 实际携带的范围。请从 响应里读它,不要假设你申请什么就拿到什么。
用不同的 scope 重新授权
Nanako 会记住用户批准过的那个 scope 字符串。如果你之后用不同的 scope 字符串发起 请求,用户会再次看到授权页,你的授权记录随之更新为新的集合。
比对的是完整字符串。profile email 和 email profile 是两个不同的值,
profile 和 profile 也是 —— 顺序或空格的差异会导致一次没有必要的二次授权。请把
scope 字符串定义成一个常量,处处复用。
令牌能访问什么
一个 OAuth access token 只能用于两个调用:
GET /oauth/userinfo | 通过 Authorization: Bearer <access_token> |
POST /oauth/revoke | 令牌作为表单字段,同时附上你的客户端凭证 |
它不能用于 Nanako 的其余接口。/api/v1/* 只接受属于已登录用户的 Nanako 会话令牌,
没有任何 scope 能改变这一点。
所以老实说:Nanako 的 OAuth 2.0 是一套身份机制。它告诉你用户是谁,目前并不代理 访问他名下的任何资源。
怎么判断令牌是否仍然有效
没有自省端点。调用 /oauth/userinfo:任何未过期、未撤销的令牌都会返回 200 且至少
带上 sub,其他情况一律 401 invalid_token。这与令牌携带哪些 scope 无关。