2022-08-04 第三方登录之 GitHub OAuth 的接入与使用
文档:https://docs.github.com/cn/developers/apps/building-oauth-apps/creating-an-oauth-app
https://docs.github.com/cn/developers/apps/building-oauth-apps/authorizing-oauth-apps
最近研究了下第三方登录和 GitHub OAuth ,下面来记录一下 GitHub OAuth 的接入与使用
关于如何创建 OAuth 应用程序
和 如何授权 OAuth 应用程序
,其实 GitHub 官方文档里面已经说的很清楚了。
只不过,关于创建这一块,按文档的说明来还是比较清晰明了的,大部分人都会。但后面这一步,如何授权 OAuth 应用程序
,就多少有点麻烦了,尤其是涉及OAuth 2.0
的部分,看起来就更让人头大。故笔者也在此记录一下心得,总结下自己的使用感受和教训。
创建 OAuth 应用程序
首先是创建部分的坑,或者说心得。
在 重定向 URL 中,官方已经指出,如果是线上的,则 重定向 URL 的主机和端口必须完全匹配回调 URL,重定向 URL 的路径必须引用回调 URL 的子目录,但如果是本地的,则 不需要匹配应用程序回调 url 中指定的端口
所以在开发阶段,为了方便本地调试,可以把应用的“Authorization callback URL(授权回调 URL)”设置为本地 URL,避免重定向问题。
授权 OAuth 应用程序
接下来就是接入 GitHub OAuth 的关键了。
为了实现这个过程,我们需要一个前端和后端。
在创建应用后,我们就可以拿到一个Client ID
和 Client Secret
,要注意的是, Client Secret
只能放在后端,千万不能放在前端,是需要保密的,不能泄露。
随后,在前端就可以向 https://github.com/login/oauth/authorize
接口请求用户的 GitHub 身份。
参考写法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| type GithubOauthAuthorizeData = {
login: string state: string redirect_uri: string } export function githubOauthAuthorize(data: GithubOauthAuthorizeData) { const query = new URLSearchParams({ ...data, client_id: 'GITHUB_CLIENT_ID', scope: '', allow_signup: 'true', }) const url = `https://github.com/login/oauth/authorize?${query.toString()}` window.location.href = url }
|
在前端合适的位置放置按钮,并绑定该函数。
在这里需要重点说明下 redirect_uri(重定向 URL)
。
当用户接受请求,GitHub 将会重定向回该 URL,同时在 URL 的查询字符串中传入参数 code
和state
。
例如:
1
| http://localhost:3000/?code=xxxxxxxxxxxxxxxxxx&state=abcdefg
|
其中 code
就是我们需要的参数,有了这个就可以去申请 access_token
,然后再去获取用户信息。
至于 state
,是用来防止跨站请求伪造攻击的,只要校验下即可。
这里也需要注意,拿到 code
之后不要在前端去申请 access_token
,因为要申请 access_token
需要用到 client_secret
, 前面也说了,client_secret(客户端密钥)
是不能泄露的,所以应该将 code
传给后端,由后端来继续后面的步骤。
接下来到了后端部分,参考代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import axios from 'axios'
type GithubAccessTokenData = { client_id: string client_secret: string code: string redirect_uri: string }
type GithubAccessTokenResponse = { access_token: string scope: string token_type: string }
export async function getGithubAccessToken(data: GithubAccessTokenData): Promise<GithubAccessTokenResponse> { return (await axios({ url: 'https://github.com/login/oauth/access_token', method: 'POST', headers: { Accept: 'application/json', }, data, }))?.data
}
export async function getGithubUserInfo(token: string): Promise<any> { return (await axios({ url: 'https://api.github.com/user', method: 'GET', headers: { Authorization: `token ${token}`, }, }))?.data }
|
个人建议在申请 access_token
的时候配置 Accept
为 application/json
,毕竟 json 格式对 js 来讲好处理很多,其他语言也类似。
然后是根据access_token
去获取用户信息,返回的结果类似于这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| { "login" : "CaoMeiYouRen", "id" : 123456, "node_id" : "xxxxxxxxxxxxxxx", "avatar_url" : "https://avatars.githubusercontent.com/u/40430746?v=4", "gravatar_id" : "", "url" : "https://api.github.com/users/CaoMeiYouRen", "html_url" : "https://github.com/CaoMeiYouRen", "followers_url" : "https://api.github.com/users/CaoMeiYouRen/followers", "following_url" : "https://api.github.com/users/CaoMeiYouRen/following{/other_user}", "gists_url" : "https://api.github.com/users/CaoMeiYouRen/gists{/gist_id}", "starred_url" : "https://api.github.com/users/CaoMeiYouRen/starred{/owner}{/repo}", "subscriptions_url" : "https://api.github.com/users/CaoMeiYouRen/subscriptions", "organizations_url" : "https://api.github.com/users/CaoMeiYouRen/orgs", "repos_url" : "https://api.github.com/users/CaoMeiYouRen/repos", "events_url" : "https://api.github.com/users/CaoMeiYouRen/events{/privacy}", "received_events_url" : "https://api.github.com/users/CaoMeiYouRen/received_events", "type" : "User", "site_admin" : false, "name" : null, "company" : null, "blog" : "https://blog.cmyr.ltd/", "location" : "中国", "email" : null, "hireable" : null, "bio" : "主攻ts/js/vue,前端工程师,B站搜草梅友仁", "twitter_username" : null, "public_repos" : 198, "public_gists" : 0, "followers" : 17, "following" : 5, "created_at" : "2018-06-20T12:50:51Z", "updated_at" : "2022-08-03T08:18:05Z" }
|
然后跟本地的用户进行一个绑定即可,这里要注意的是,GitHub 用户的 id 是唯一的,用户名 login
是可以修改的,所以应该跟 id
建立关系。
到这一步就算完成了整个 GitHub OAuth 的对接,拿到用户数据之后要怎么做就是自己的事情了,看项目需求即可。
本文作者:草梅友仁
本文地址: https://blog.cmyr.ltd/archives/e53f109b.html
版权声明:转载请注明出处!