OAuth2第三方登录实践

6,983 阅读3分钟

OAuth2 是一个开放授权标准,旨在让用户允许第三方应用去访问该用户在某服务器中的特定私有资源,而可以不提供其在某服务器的账号密码给到第三方应用。

1、授权流程

  • 四大角色

Resource Owner:资源所有者
Resource Server:资源服务器
Client:第三方应用客户端
Authorication Server:授权服务器

  • 流程

1、第三方应用发起Authorization Request,一般需要提供以下参数(授权许可类型为授权码Authorization Code时):
a) response_type:必选。值固定为code
b) client_id:必选。第三方应用的标识ID
c) state:推荐。Client提供的一个字符串,服务器会原样返回给Client
d) redirect_uri:必选。授权成功后的重定向地址。
e) scope:可选。表示授权范围

2、用户授权登录后,第三方应用会获取到一个Authorization Grant(授权许可),授权许可是一个代表资源所有者授权(访问受保护资源)的凭据,客户端用它来获取访问令牌。

3、第三方拥有授权许可后,提供以下参数请求Authorization Server(授权许可类型为Authorization Code时):
a) grant_type:必选。固定值authorization_code
b) code: 必选。Authorization Response 中响应的code
c) redirect_uri:必选。必须和Authorization Request中提供的redirect_uri相同。
d) client_id:必选。必须和Authorization Request中提供的client_id相同。

4、Authorization Server会返回如下典型的信息:
a) access_token:访问令牌。
b) refresh_token:刷新令牌。
c) expires_in:过期时间。

具体可参考[认证 & 授权] 1. OAuth2授权

2、微信第三方登录

  • 前置准备

微信开放平台注册开发者账号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,并且设置好回调域名(不带协议),可开始接入流程。

  • 授权流程

1、第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数。
ps:code是第三方用来获取access_token的,code的超时时间为10分钟,一个code只能成功换取一次access_token即失效。code的临时性和一次性保障了微信授权登录的安全性。

2、通过code参数加上AppIDAppSecret等,通过API换取access_token(接口调用凭证)。

3、通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

  • 代码实现
export function oauthRedirect(scope = 'snsapi_userinfo', state = 'wechat') {
    //  已经授权过的可以不用授权了 过期code 需要清空
    if (code) {
       return
    }
    let callbackUrl = encodeURIComponent(window.location.href)
    const host = `https://open.weixin.qq.com/connect/oauth2/authorize`
    let url = `${host}?appid=${APPID}&redirect_uri=${callbackUrl}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`
    window.location.href = url
}

其中redirect_uri为登录之后的回调地址,要与在网站应用里设置的回调域名一致,否则会报错;scope为授权作用域,代表用户授权给第三方的接口权限(选择的是snsapi_userinfo,获取用户个人信息);state用于保持请求和回调的状态,授权请求后原样带回给第三方。

用户允许授权后,将会重定向到redirect_uri的网址上,并且带上codestate参数,若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数。
具体信息可见微信官方文档

3、微博第三方登录

  • 前置准备

通过新浪微博开放平台去注册一个应用,拿到App Key,同时设置好授权回调地址。

  • 授权流程

1、第三方发起微博授权登录请求,微博用户允许授权第三方应用后,微博会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数。

2、通过code参数加上client_idclient_secret等,通过API换取access_token(接口调用凭证)。

3、通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

  • 代码实现
export function weiboOauthRedirect() {
    if (code) {
        return
    }
    let callbackUrl = encodeURIComponent(window.location.href)
    const host = `https://api.weibo.com/oauth2/authorize`
    let url = `${host}?state=wb&client_id=${APPID}&response_type=code&redirect_uri=${callbackUrl}?`
    window.location.href = url
}

具体参数信息可见微博官方文档

3、google第三方登录

  • 前置准备

通过Google APIs控制台去创建一个项目,选择创建凭据 -> OAuth 客户端 ID -> 网页应用,之后输入 JavaScript 来源、重定向 URI,拿到的客户端ID用于后续操作。

  • 授权流程

1、第三方发起google授权登录请求,google用户允许授权第三方应用后,google会拉起应用或重定向到第三方网站,回调函数中传回code参数。

2、通过code参数加上client_idclient_secret等,通过API换取access_token(接口调用凭证)。

3、通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

具体信息可见google官方文档

  • 代码实现
// 首先需要先进行初始化
start() {
    $scriptjs(['https://apis.google.com/js/api:client.js'], () => {
        let gapi = window.gapi
        gapi &&
            gapi.load('auth2', () => {
                this.auth2 = gapi.auth2.init({
                    client_id: client_id,
                    cookiepolicy: 'single_host_origin',
                    scope: 'profile'
                })
            })
    })
}
// 获取google授权并进行登录
jumpGoogle() {
    if (this.auth2) {
        this.auth2
            .grantOfflineAccess()
            .then(async authCode => {
                let res = await googleLogin(authCode.code)
                res && this.handleRegister(res)
            })
            .catch(e => {
                e.msg && this.$toast(e.msg)
            })
    } else {
        this.$toast('您的装置暂不支持Google Play服务')
    }
},

具体信息可见google官方文档

4、Facebook 第三方登录

  • 前置准备

通过facebook开发者平台去注册一个应用,拿到App Key,同时设置好授权回调地址(仅支持https)。

  • 授权流程

1、第三方发起facebook授权登录请求,facebook用户允许授权第三方应用后,facebook会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数。

2、通过code参数加上client_idclient_secret等,通过API换取access_token(接口调用凭证)。

3、通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

  • 代码实现
export function facebookOauthRedirect(cb) {
    if (code) {
        return
    }
    // 先要判断是是否能访问外网
    let callbackUrl = encodeURIComponent(window.location.href)
    const host = `https://www.facebook.com/dialog/oauth`
    let url = `${host}?client_id=${clientId}&redirect_uri=${callbackUrl}&code=acgon&state=fb`
    $scriptjs(['https://code.jquery.com/jquery-3.1.1.min.js'], () => {
        window.jQuery.ajax({
            type: 'GET',
            dataType: 'jsonp',
            url: 'https://m.facebook.com/dialog/oauth',
            timeout: 2000,
            complete: function(XMLHttpRequest) {
                if (XMLHttpRequest.status === 200) {
                    window.location.href = url
                } else {
                    cb()
                }
            }
        })
    })
}

具体信息可见facebook官方文档