专栏名称: 区块链技术学习
致力于区块链技术的学习和普及,对区块链技术和相关企业事件进行深度分析和研判,探索去中心化账本技术应用领域。
目录
相关文章推荐
BetterRead  ·  瞧,这个人讲信仰 ·  2 天前  
康石石  ·  爱丁堡录取率高达70%!艺术生有福了! ·  2 天前  
51好读  ›  专栏  ›  区块链技术学习

WebAuthn:用于JavaScript的服务器和客户端强认证库

区块链技术学习  · 公众号  ·  · 2019-08-06 12:30

正文

区块链技术学习(微信号:Blockchain1024)翻译

原文链接:https://marmelab.com/blog/2019/06/24/web-authn-fido2-open-source-package.html


浏览器支持名为 WebAuthn 的新安全标准,以促进强认证。我们开源了一个库来促进它的实现。


强认证很复杂


让我们谈谈安全问题


密码很糟糕:当密码足够长、足够安全的时候,就很难记住了。我们需要为每个新服务生成一个新密码,并且禁止大约5.5亿个密码,因为它们是数据泄露的一部分。


有哪些替代身份验证方法?我们需要依靠拥有因素(用户拥有的东西,比如安全令牌)或内在因素(用户所拥有的东西,比如指纹),而不是知识因素(用户知道的东西)。或者,理想情况下,结合使用这些方法(即多因素身份验证,或MFA)。


遗憾的是,并非每个用户都拥有带指纹传感器的设备,而且软件令牌(如Google身份验证器应用程序)要求用户将一次性密码(OTP)从令牌复制到他们想要登录的服务。换句话说:强认证对于使用的终端来说是很麻烦的。


一个很好解决的方案是 连接令牌 ,即插入计算机的设备,如USB密钥。这是一个占有因素,你可以在任何电脑上使用它。在连接到计算机时,你无需手动复制OTP。它使用公钥加密技术,只需单击即可验证质询。


这是一个连接的令牌,称为YubiKey,由Yubico公司销售:



但是,需要访问令牌的服务必须知道其协议。直到最近,只有胖客户端才能与连接的令牌进行通信。这排除了在浏览器中运行的服务。


WebAuthn / Fido2:一个W3C标准,W3C标准将强认证带入浏览器


输入FIDO2,这是浏览器中强认证的标准。引用维基百科:


FIDO2的核心是由W3C Web 身份验证 (WebAuthn)标准和FIDO 客户端到身份验证器协议(CTAP)组成。


WebAuthn标准是一组JavaScript API,用于在浏览器中与连接的令牌进行通信。在撰写本文时,大多数桌面浏览器都支持它,覆盖全球67%的用户:



它允许做的是使用连接的令牌注册并登录到Web应用程序。无需密码要:只需插上密钥,按下按钮,就可以了。


如果你曾经使用过YubiKey或类似的东西,你会同意这种体验比输入密码要好一个数量级。但是,为什么我们不在我们的web应用程序中使用WebAuthn呢?


客户端-服务器协议很难


还记得FIDO2项目中的客户端到认证器协议规范(CTAP)吗?它是一种协议,意味着它的实现取决于开发人员,问题就在这里。


已经有一些实现,你可以在GitHub和WebAuthn.io网站上找到。


WebAuthn.io官网: https://webauthn.io/



这些实现通常是由与FIDO2联盟成员开发的概念验证,这意味着这些库仅在少数情况下工作,并且它们的文档要么不存在,要么难以理解。


例如,下面是FIDO联盟自己编写的JavaScript webauthn-demo自述文件:


webauthn-demo地址: https://github.com/fido-alliance/webauthn-demo



它是JavaScript中唯一的一个。


介绍@webauthn包


现在,我们介绍 @webauthn/client @webauthn/server 这两个NPM包,它们将帮助JavaScript开发人员在实践中实现FIDO2。我们还在这些包中包含了一个示例客户端和服务器。


下面是如何在客户端实现注册按钮:


import { solveRegistrationChallenge, solveLoginChallenge } from '@webauthn/client';

const loginButton = document.getElementById('login');
const registerButton = document.getElementById('register');
const messageDiv = document.getElementById('message');

const displayMessage = message => {
    messageDiv.innerHTML = message;
}

registerButton.onclick = async () => {
    const challenge = await fetch('https://localhost:8000/request-register', {
        method'POST',
        headers: {
            'content-type''Application/Json'
        },
        bodyJSON.stringify({ id'uuid'email'test@test' })
    })
        .then(response => response.json());
    const credentials = await solveRegistrationChallenge(challenge);

    const { loggedIn } = await fetch(
        'https://localhost:8000/register'
        {
            method'POST',
            headers: {
                'content-type''Application/Json'
            },
            bodyJSON.stringify(credentials)
        }
    ).then(response => response.json());

    if (loggedIn) {
        displayMessage('registration successful');
        return;
    }
    displayMessage('registration failed');
};

loginButton.onclick = async () => {
    const challenge = await fetch('https://localhost:8000/login', {
        method'POST',
        headers: {
            'content-type''Application/Json'
        },
        bodyJSON.stringify({ email'test@test' })
    })
    .then(response => response.json());


    const credentials = await solveLoginChallenge(challenge);
    const { loggedIn } = await fetch(
        'https://localhost:8000/login-challenge'
        {
            method'POST',
            headers: {
                'content-type''Application/Json'
            },
            bodyJSON.stringify(credentials)
        }
    ).then(response => response.json());

    if (loggedIn) {
        displayMessage('You are logged in');
        return;
    }
    displayMessage('Invalid credential');
};


@webauthn/client公开的两个方法只是Navigator.credentials API的一个瘦包装器。实际上,浏览器管理加密挑战,这样开发人员就不会尝试自己完成(错误的方式)。


下面是服务器部分,使用Node.js和Express.js:


const {
    generateRegistrationChallenge,
    parseRegisterRequest,
} = require('@webauthn/server');

const






请到「今天看啥」查看全文