使用 Cloudflare Application Access 对托管站点进行管控访问
开发应用时,常常使用注册登录的方式保护应用的访问,基本上每每开发一个应用都需要重新做一遍,尽管界面可能不一样,但内部实现确大同小异。是否可以有一个SAAS的平台定制化的对登录态进行封装,让开发者不必每次做这方面的工作。开源方面有 logto 的实现,本文将会介绍如何使用 Cloudflare Application Access 对自有应用进行保护。
1. 目标
显示”The Server is Running”内容的站点,地址是 https://my.0x02.link,在访问之前使用 Cloudflare Application Access 加一层登录态的验证,提供三种登录方式:
- One-Time PIN,发送六位验证码到指定邮箱中,验证登录
- Github,使用Github账号进行登录
- Google,使用Google账号进行登录
2. 前提
- 可通过域名访问的的自有站点,类似于 https://my.0x02.link
- 这个站点的域名需要托管到 Cloudflare
怎么托管? 无论在哪里购买的域名,只需要将域名的 DNS 切换成 Cloudflare 的 DNS 即可实现,具体在 Cloudflare 控制台添加站点时,按步骤进行操作。
3. 配置方式
下面将会依次完成目标中提到的三种验证方式
3.1. One-Time Pin
One-Time PIN,也叫 OTP 或一次性 PIN,是指只能使用一次的密码进行登录鉴权。也是 Cloudflare 默认提供的方式,配置最为简单。
进入 Cloudflare Dashboard 页面,点击左侧菜单”Zero Trust”,点击左侧菜单”Access” - “Applications”
点击按钮”Add an Application”,选择”Self-hosted”,进入应用配置页面,”Application name”随意填写,”Session During”表示会话的有效期,”Subdomain”子域名,”Domain”是具体控制哪个域名,其他配置默认。
点击页面底部”下一步”,进入规则配置页面,”Policy name”随便输入,”Selector”规则选择只接受以”qq.com、163.com”结尾的邮箱做为OTP的登录名。
点击页面底部”下一步”,这个页面保持默认配置,点击页面底部”Add Application”,完成配置工作。
打开访问域名,会看见 Cloudflare 前置拦截了请求,做了 OTP 的登录态验证,输入有效的邮箱收取验证码后可以正常访问背后的应用。
3.2. Github
在原有基础上支持 Github 账号的登录,正常的做法是开发的业务应用需要集成 Github 的开放API,做鉴权,但如果使用 Cloudflare 只要配置即可实现,下面介绍配置明细。
目的是在 Github 上获取 app id 和 client secret,打开 Github 首页,点击右上角我的头像,选择”Settings”
页面拉到最下面,点击左侧菜单”Developer Settings”,选择”OAuth Apps”,点击”New OAuth App”创建新的授权应用
注册 OAuth 应用的表单页面,”Application name”随意填写,”Homepage URL”是Cloudflare的 Team URL 地址,Team URL获取方式见附录,”Authorization callback URL”同”Homepage URL”,加上回调路径 /cdn-cgi/access/callback
,填完点击”Register application”跳转到明细页面,点击拷贝其中的Client ID和Client secrets
有了Client ID和Client secrets,回到 Cloudflare,进入”Zero Trust”,点击左侧”Settings”-“Authentication”,在”Login methods”中点击”Add new”,选择”Github”,填入Client ID和Client secrets,配置完成。
3.3. Google
在原有基础上支持 Google 账号的登录,打开 Google Cloud Console,新建项目,项目名称随意,无组织
选择刚才创建的工程,在下面快速访问中选择”API和服务”
点击左侧”OAuth 同意屏幕”,选择”外部 “,点击创建
“应用名称”随意,”用户支持电子邮件”选择自己的邮箱,最下面的”开发者联系信息”也输入自己的邮箱,其他都是界面的样式,保持默认,点击最下面”保存并继续”,进入下一步
点击”添加和移出范围”,右侧弹出API列表,在”过滤条件”上搜索”userinfo.email”,选择并点击”更新”,页面最下面”保存并继续”,进入下一步到测试用户阶段,保持默认,继续保存,进入下一页拉到最下面,点击”返回信息中心”
左侧菜单”凭据”-“创建凭据”-“OAuth 客户端ID”,进入”创建 OAuth 客户端 ID”页面
应用类型选择”Web 应用”,”名称”随意,”已获授权的 JavaScript 来源”输入Cloudflare的 Team URL 地址,Team URL获取方式见附录,”已获授权的重定向 URI”输入回调地址,即 Cloudflare Team URL 加上回调路径 /cdn-cgi/access/callback
,点击下面”创建”完成配置操作,弹出密钥信息,复制其中的客户端 ID和客户端密钥。
按照 章节3.2 Github 一样,将从Google获取到的客户端 ID和客户端密钥配置到 Cloudflare 的 Authorization 中。
4. 最终结果
在 Cloudflare 的 Authorization 中,看见目前鉴权已经支持了三种方式,可以点击”Test”链接,以确定配置的 Github 和 Google 是否有效
回到在配置 OTP 阶段的访问控制,左侧菜单”Access”-“Applications”,选择之前创建的应用,点击”配置”,在Tab页”Authorization”中就可以选择 Github 和 Google 的登录方法,选择后保存。
访问我们控制的域名站点,出现 Cloudflare 为我们前置的登录鉴权页面,全程没有写一行代码,完全配置。
5. 登录信息
Cloudflare 前置帮我们做了登录校验,无论是 OTP、Github 还是 Google 方式的登录,后置应用肯定是期望拿到用户的登录信息的,Cloudflare 分别在请求头 Header 和 Cookie 里帮我们做了补充,下面的例子可作为参考,只要有请求的 request
// 登录态过期,访问时弹出 Cloudflare 登录鉴权页面
// 登录后跳转到后置应用时会带上下面两个消息头
const cfAccessUserEmail = requestHeaders.get('Cf-Access-Authenticated-User-Email');
const cfAccessJwt = requestHeaders.get('Cf-Access-Jwt-Assertion');
if (cfAccessUserEmail && cfAccessJwt) {
// 做用户保存动作
// ......
}
// 在登录态有效期内直接访问,都会在 Cookie 中带上 CF_Authorization 值,不会有上面的 cfAccessUserEmail 和 cfAccessJwt
// 此值就是上面的 cfAccessJwt,即 cfAuthorization == cfAccessJwt
const cfAuthorization = request.cookies.get('CF_Authorization');
console.info('cfAuthorization', cfAuthorization);
附录
Team URL获取方式
在 Cloudflare Dashboard 页面进入 “Zero Trust”,点击左侧”Settings”,然后再选择”Custom Pages”可以看到Team domain,这个就是
版权所有,本作品采用知识共享署名-非商业性使用 3.0 未本地化版本许可协议进行许可。转载请注明出处:https://www.wangjun.dev//2023/08/how-to-user-cloudflare-access/