学习笔记 | 简单设计一个OAuth认证回调服务器
前言
暑假待在家里没得事做,想做一个移动端的博客写作客户端,由于我的博客内容是储存在github上的,所以在开发的过程中,我需要学习一下github OAuth认证流程。简单的了解了一下 github的OAuth认证流程大致是当用户认证成功之后,会下发一个code给认证地址,然后通过code和客户端id以及客户端密钥向github发起请求,便可以得到用户的access token。我一开始以为这个code到access token的流程必须要一个服务器才可以完成,但是突然想到这种流程化的事情,不需要保存状态的,像cloudflare worker这样的serverless平台,应该也可以办到,于是用cloudflare worker简单的做了一个认证回调服务器。
代码
先解析 URL 上的参数:code、state,还有可能出现的 error。这里有个容易漏掉的点——用户在授权页点”取消”的时候,GitHub 不会给 code,而是直接带 error=access_denied 跳回来,所以必须先判断 errorParam,不然后面拿着空 code 去请求 GitHub,只会得到一个莫名其妙的报错。
拿到正常的 code 之后,就是 POST 请求打到 https://github.com/login/oauth/access_token,body 里带上 client_id、client_secret、code、redirect_uri,这一步是服务端对服务端换 token,client_secret 只能放在这里,绝对不能出现在 App 里,不然反编译一下就全露了。这里踩了个小坑<请求头一定要加> Accept: application/json,不加的话 GitHub 默认返回的是 key=value&key2=value2 这种查询字符串格式,还得自己手动解析,挺麻烦的。
换完之后,不管是换 token 失败、GitHub 返回业务错误(比如 bad_verification_code,也就是 code 过期或者已经被用过了)、还是成功拿到了 access_token,最后都统一走 redirectToApp 这一个函数 302 回 App:
这样设计的好处是,App 那边只需要检查跳转回来的 URL 上有没有 access_token,就能判断整个流程走没走通,完全不用关心中间到底是哪个环节出的问题。
后记
弄完之后,才发现其实连服务器都不需要,浏览器是支持输入应用app scheme的,在浏览器通过这个跳转到应用内部,让应用接收code,然后在应用内部实现code转access token的过程。不过这样的话,就得把客户端id和客户端密钥写进应用内部,如果被人反编译出来,就会有密钥泄露的风险。而且如果是设计更复杂的应用,涉及到第三方账号的绑定,数据库的查询读写,这些操作都应该放到云端认证回调服务器上去执行,而不应该放在本地客户端里面。把认证回调服务器写成本地APP scheme这种方案只能临时用于没有服务器的情况,不能放在正式的生产环境。
index.js
展开收起
wrangler.toml
展开收起