Active Directory 使用错误的凭据进行身份验证

Active Directory Authenticates with Bad Credentials

我正在使用 npm 包 activedirectory 连接到我公司的域控制器,以便在内部网站上对用户进行身份验证。该计划是让用户将他们的 windows 域凭据输入网站的登录页面(使用 React 编写)。该网站会将凭据转发到后端 Express 服务器,如下所示:

const express = require('express');
const bodyParser = require('body-parser');
const ActiveDirectory = require('activedirectory');

const app = express();
app.use(bodyParser.urlencoded({
    extended: false,
}));

app.get('/ldap', (request, response) => {
    // set http header for json
    response.setHeader('ContentType', 'application/json');

    // get the username and password from the query
    const username = request.query.username + '@internal.mycompany.com';
    const password = request.query.password;
    console.log(username, password);

    // create a new active directory connection
    let activeDirectory = new ActiveDirectory({
        url: 'LDAP://internal.mycompany.com',
        baseDN: 'DC=mycompany,DC=com',
    });

    // attempt authentication
    activeDirectory.authenticate(username, password, (error, authenticated) => {
        if(error) {
            console.log('ERROR: ' + JSON.stringify(error));
        }
        else {
            console.log('Authentication successful');
        }

        // respond
        response.send(JSON.stringify({
            error: error,
            authenticated: authenticated,
        }));
    });

});

app.listen(3001, () => {
    console.log('Express server running on port 3001.');
});

单击 'Log In' 按钮时,React 前端会执行此操作:

login() {
    console.log('authenticating with username: ', this.state.username, ' and password: ', this.state.password);
    fetch(`/ldap/?username=${encodeURIComponent(this.state.username)}&password=${encodeURIComponent(this.state.password)}`).then((response) => {
        return response.json();
    }).then((response) => {
        console.log(response);
        this.props.setLoggedIn(response.authenticated);
        this.setState({
            loginFailed: !response.authenticated,
            redirectToHome: response.authenticated,
        });
    });
}

它调用 fetch 请求 Express 服务器验证凭据,并相应地设置一些全局登录状态。它还将本地状态设置为在登录尝试失败时显示错误消息,或者在登录尝试成功时将用户重定向到主网站主页。

将用户名和密码留空会产生以下响应:

{
    error: {
        code: 49,
        description: "The supplied credential is invalid",
        errno: "LDAP_INVALID_CREDENTIALS",
    },
    authenticated: false,
}

输入有效的用户名和密码会产生以下响应:

{
    error: null,
    authenticated: true,
}

到目前为止,这一切都符合预期。

但是,输入 随机字符 作为用户名和密码会产生 2 个响应之一。它要么成功验证,这不应该发生,要么它给出:

{
    error: {
        lde_dn: null,
        lde_message: "80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db1",
    },
    authenticated: false,
}

问题: 为什么给域控制器垃圾凭据会导致它 return authenticated: true?为什么只是有时?有些信息必须缓存或记住某处。我尝试重新启动 Express 服务器,并尝试等待一天让某些东西过期。

注意:我打算encrypt/scramble密码,这样它们就不会以纯文本形式发送,但如果有更好的发送方式安全地,请就如何改进这一点发表评论。但目前主要问题是关于不正确的 Active Directory/LDAP 身份验证。

此信息:https://www.rfc-editor.org/rfc/rfc4513#section-6.3.1 本质上告诉我们,获得 authenticated: true 实际上可能没有任何意义。我想出的解决方案是尝试查询 Active Directory 以查看刚刚通过身份验证的用户是否存在 and/or 尝试以新身份验证的用户身份执行 an/some 操作。如果操作失败,则登录无效。

另外,上面的代码有错误。 baseDN 应该是 'DC=internal,DC=mycompany,DC=com'.