第三方登录凭证管理

对于用户而言,注册账号密码是一件非常麻烦的事情,不但注册过程繁琐且花时间,同时也提高了用户的账号维护成本。因此如果网站能够提供第三方登录,让用户能够直接复用一些现有且常用的网站账号,将能够大大提高用户体验。

接入第三方登录 API

一些大型的站点平台都会开放相应的第三方登录接口和说明文档,如国内的有:

国外的有:

保存第三方登录凭证

同样需要调用方法 navigator.credentials.store() 进行第三方登录凭证存储,只不过存入的凭证类型为 FederatedCredentialFederatedCredential 同样实现了 Credential 接口,同时还新增了 provider 字段作为第三方登录提供方的标识符。因此 FederatedCredential 初始化参数对象应包含以下信息:

  • id: 必须 账户名
  • provider: 必须 第三方登录提供方网址
  • name: 非必需 用户名
  • iconURL: 非必需 用户头像

其中 provider 要求必须是完整的带协议头的 URL 地址。我们可以在控制台做如下实验:

provider 格式实验

可以看到,浏览器会校验 provider 的格式,当格式不符合 URL 格式时会抛出错误。

这样,我们就可以使用 FederatedCredential 对第三方登录信息进行存储啦。

例如:

  1. /* global THIRD_PARTY_PROVIDER */
  2. thirdPartyLogin()
  3. .then(function (profile) {
  4. if (navigator.credentials) {
  5. let cred = new FederatedCredential({
  6. id: profile.email,
  7. provider: THIRD_PARTY_PROVIDER,
  8. name: profile.name,
  9. iconUrl: profile.iconUrl
  10. });
  11. return navigator.credentials.store(cred);
  12. }
  13. return profile;
  14. })
  15. .then(function (profile) {
  16. // 后续操作
  17. })
  18. .catch(function (err) {
  19. // 错误处理
  20. });

读取第三方登录凭证

需要调用方法 navigator.credentials.get() 方法进行第三方登录凭证的读取。

在前文凭据获取章节中提到,navigator.credentials.get(options) 方法传入参数包含一个字段 federated,可以通过这个字段去读取第三方登录的凭证信息。

  • options.federated: 第三方登录
    {Object}
    • providers:
      {Array} 联合登录账号供应者 id 组成的数组

例如:

  1. navigator.credentials.get({
  2. federated: {
  3. providers: ['https://www.baidu.com', 'https://www.weibo.com', 'https://www.github.com']
  4. }
  5. });

这些 providers 需要与 FederatedCredential 第三方登录凭证信息的 provider 相一致。

这样假设存入的第三方登录凭证如下:

  1. let cred = new FederatedCredential({
  2. id: '123456',
  3. provider: 'https://www.baidu.com',
  4. name: '测试百度用户名',
  5. iconUrl: 'path-to-icon'
  6. });

则在弹出的账号选择列表中,就可以看到如下所示的账号信息:

第三方账号信息

那些带有提供方描述字样的信息就是对应的第三方登录凭证信息。没错,不同于密码凭证信息,第三方登录凭证信息会拿 id 字段作为账号的标识。

对于不同的第三方登录具有不同的处理方式,因此在获取到第三方登录凭证信息之后,需要通过 typeprovider 字段进行凭证信息分类处理,如:

  1. navigator.credentials.get({
  2. password: true,
  3. federated: {
  4. providers: ['https://www.baidu.com', 'https://www.weibo.com']
  5. }
  6. })
  7. .then(function (cred) {
  8. if (cred) {
  9. switch (cred.type) {
  10. case 'password':
  11. // PasswordCredential 凭证处理
  12. case 'federated':
  13. // FederatedCredential 凭证处理
  14. switch (cred.provider) {
  15. case 'https://www.baidu.com':
  16. // 调起百度第三方登录
  17. case 'https://www.weibo.com':
  18. // 调起微博第三方登录
  19. }
  20. }
  21. }
  22. });

第三方登录示例

完整的示例代码可以 戳这里

第三方登录界面如下:

第三方登录界面

点击登录界面的百度登录按钮,即可触发模拟第三方登录。相关代码如下:

  1. <button id="login-btn" data-provider="https://www.baidu.com">百度登录</button>
  1. $btn.addEventListener('click', function () {
  2. let provider = this.dataset.provider;
  3. // 假装 fetch('./third-party.json') 是调用百度第三方登录的过程
  4. fetch('./third-party.json')
  5. .then(res => {
  6. if (res.status === 200) {
  7. return res.json();
  8. }
  9. return Promise.reject(res.status);
  10. })
  11. // 此处假装第三方登录并授权成功
  12. .then(data => {
  13. // 此处调用凭证管理 API 进行第三方登录信息存储
  14. if (navigator.credentials) {
  15. // 生成第三方登录凭证
  16. let cred = new FederatedCredential({
  17. id: data.uid,
  18. provider: provider,
  19. name: data.name,
  20. iconURL: data.icon
  21. });
  22. // 存储
  23. return navigator.credentials.store(cred)
  24. .then(() => {
  25. return data;
  26. });
  27. }
  28. return Promise.resolve(data);
  29. })
  30. // 存储完成后再跳转至登录成功页
  31. .then(data => {
  32. window.location.href = './main.html?from=third-party&username=' + data.name;
  33. });
  34. });

其中模拟第三方授权登录的 third-party.json 返回如下:

  1. {
  2. "name": "测试百度用户名",
  3. "uid": "123456",
  4. "icon": "https://lavas-project.github.io/pwa-demo/credential-demo/images/logo-48x48.png"
  5. }

跳转到成功页时将提示如下信息:

是否保存账号对话框

点击保存并重新打开登录页面时,将弹出如下账号选择器:

账号选择器

可以看到提供方为 www.baidu.com 的账号信息显示在账号选择器列表中。对应的代码如下所示:

  1. if (navigator.credentials) {
  2. navigator.credentials.get({
  3. password: true,
  4. federated: {
  5. providers: ['https://www.baidu.com']
  6. }
  7. })
  8. .then(cred => {
  9. if (cred) {
  10. switch (cred.type) {
  11. case 'federated':
  12. // FederatedCredential 凭证处理
  13. switch (cred.provider) {
  14. case 'https://www.baidu.com':
  15. // 调起百度第三方登录
  16. window.location.href = './main.html?from=third-party&username=' + cred.name;
  17. }
  18. // ...
  19. }
  20. }
  21. });
  22. }