本文源码地址:https://github.com/Spring-Security-China/oauth2-client-login-js-github
大纲
概述
实现思路分析
在Github官网注册OAuth2应用
代码实现
运行与演示
总结
概述
为了达到“最简洁”这个目标,大家是不是希望可以使用纯前端的方式,只一个html在浏览器中运行,就完成Github第三方登录功能呢?只能说理想很丰满,现实很骨感,因为OAuth2协议的限制和一些安全性需求,我们仍然需要前端和后端相互配合才可以实现Github登录。
Github的第三方登录功能背后的技术实际上是OAuth2协议,OAuth2协议本身有一定的复杂性,大家可以参考公众号文章《OAuth2核心协议概览》做一些简单理解。
我们知道OAuth2协议中有OAuth2授权服务器、资源服务器、OAuth2客户端和用户代理这四个角色。与其他很多互联网平台如微信公众平台、Google开放平台、OKTA等等一样,Github也同时是OAuth2授权服务器和资源服务器,浏览器是用户代理。而本文的代码示例,实际上就是一个OAuth2客户端。
本文通过几行js代码,在不需要大家了解OAuth2协议细节的情况下,就可以实现Github第三方登录的功能,同时让大家快速而直观地感受下OAuth2核心协议。
实现思路分析
如何接入Github登录?看Github官网:https://developer.github.com/apps/building-oauth-apps 。
获取token需要两个步骤:
获取code:浏览器访问 https://github.com/login/oauth/authorize 同时传递回调地址等参数
使用code交换token:携带code发起POST请求调用 https://github.com/login/oauth/access_token
是不是感觉很简单,我们直接写个html页面,在页面中写两个方法就解决了?就像这样:
function getCode(){
window.location.href = "https://github.com/login/oauth/authorize"+...
}
function getToken(code){
...POST "https://github.com/login/oauth/access_token" 获取token...
}
但这种方案是行不通的。因为首先“/oauth/access_token”接口不允许跨源访问(关于什么是跨源,可以参考《彻底理解浏览器同源策略SOP》和《彻底掌握CORS跨源资源共享》两篇文章),也就是说浏览器调用这个接口后无法获取响应。其次token暴露在浏览器端会增加token泄露的风险。实际上根据OAuth2协议,通过code交换token的这个接口流程属于后端流程(“back-end flow”),是后端调用后端的流程类型。
那么只好增加复杂性,引入后端。实现一个最简洁的JS前端+JS后端的Github登录代码示例。逻辑流程图如下:
在Github官网注册OAuth2应用
首先需要在Github官网注册一个新的OAuth2应用,地址是:https://github.com/settings/applications/new
Application Name:必填,应用名称, 设置为:
oauth2-client-login-js-github
。Homepage URL: 必填,应用主页,设置为
http://localhost:8080
。Application description: 选填,应用的说明,置空即可。
Authorization callback URL: 必填,OAuth认证的重定向地址,本地开发环节可设置为
http://localhost:8080
。
当用户通过浏览器成功登录Github,并且用户在批准页(Approva Page)授权允许注册的客户端应用访问自己的用户数据后,Github会将授权码(code)通过重定向方式传递给客户端应用。
填写无误后,点击 Registerappcation
按钮,注册成功后,获取到 clientId
和 clientSecret
。
代码实现
源码地址:https://github.com/Spring-Security-China/oauth2-client-login-js-github
server.js是nodejs实现的后端
loginGithub.html是普通html模拟的前端
前端示例代码loginGithub.html
...略
onclick="handleLoginGithub()">使用Github登录