You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用BotAuth Node.js为Microsoft Bot Framework添加自定义第三方登录提供商

用BotAuth Node.js实现自定义第三方认证提供商(附替代方案)

当然可以用BotAuth实现自定义提供商!我之前在基于Node.js的Bot Framework项目里做过类似需求,下面给你详细说怎么操作,另外也会推荐更现代的替代方案——毕竟BotAuth的维护已经有些年头了。

一、用BotAuth实现自定义提供商

BotAuth的核心是通过OAuth2Provider类封装不同的OAuth2提供商,我们只需要继承这个类,根据目标第三方API的认证规则重写必要方法就行:

1. 创建自定义提供商类

新建一个CustomOAuthProvider.js文件,实现自己的提供商逻辑:

const { OAuth2Provider } = require('botauth');

class CustomProvider extends OAuth2Provider {
    constructor(settings) {
        super(settings);
        // 替换成你的第三方API认证端点
        this.authUrl = 'https://your-custom-api.com/oauth/authorize';
        // 替换成你的第三方API Token获取端点
        this.tokenUrl = 'https://your-custom-api.com/oauth/token';
        // 默认权限范围,可通过settings覆盖
        this.scope = settings.scope || 'basic_access';
    }

    // 重写生成授权URL的方法,适配目标API参数要求
    getAuthorizationUrl(session, state) {
        const params = {
            client_id: this.clientId,
            redirect_uri: this.redirectUri,
            scope: this.scope,
            state: state,
            response_type: 'code' // 大多数OAuth2用code模式
        };
        // 拼接参数到授权URL
        const url = new URL(this.authUrl);
        Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
        return url.toString();
    }

    // 重写获取Token的方法,适配目标API请求格式
    async getToken(code) {
        const params = new URLSearchParams();
        params.append('grant_type', 'authorization_code');
        params.append('code', code);
        params.append('client_id', this.clientId);
        params.append('client_secret', this.clientSecret);
        params.append('redirect_uri', this.redirectUri);

        const response = await fetch(this.tokenUrl, {
            method: 'POST',
            body: params,
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });

        if (!response.ok) {
            throw new Error(`获取Token失败: ${response.statusText}`);
        }
        return response.json();
    }
}

module.exports = CustomProvider;

2. 在Bot中注册并使用自定义提供商

在你的Bot主文件里初始化BotAuth,添加自定义提供商,并在对话中触发认证:

const BotAuth = require('botauth');
const CustomProvider = require('./CustomProvider');
const builder = require('botbuilder');

// 初始化Bot连接器
const connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD
});

// 初始化BotAuth
const botauth = new BotAuth({
    secret: 'your-random-bot-secret', // 用于加密状态的密钥
    baseUrl: 'https://your-bot-deployment-url.com' // 你的Bot公网地址
});

// 注册自定义提供商
botauth.provider('custom-api', new CustomProvider({
    clientId: 'your-custom-api-client-id',
    clientSecret: 'your-custom-api-client-secret',
    redirectUri: 'https://your-bot-deployment-url.com/api/oauth/custom-api/callback',
    scope: 'read write'
}));

// 创建Bot实例
const bot = new builder.UniversalBot(connector);

// 添加登录对话
bot.dialog('/login', [
    async (session) => {
        // 触发自定义提供商的认证流程
        await botauth.authenticate(session, 'custom-api', (err, user) => {
            if (err) {
                session.send(`登录出错了:${err.message}`);
            } else {
                session.send(`登录成功!你的Token是:${user.accessToken}`);
                // 这里就可以用user.accessToken调用第三方API了
            }
        });
    }
]);

// 设置默认对话
bot.dialog('/', (session) => {
    session.send('欢迎!输入「登录」开始认证');
    session.beginDialog('/login');
});

3. 配置回调路由

BotAuth需要处理第三方API的回调请求,所以在你的Express/Restify服务器中添加路由:

const express = require('express');
const server = express();

// 处理Bot的消息请求
server.post('/api/messages', connector.listen());

// 处理OAuth回调
server.post('/api/oauth/:provider/callback', (req, res) => {
    botauth.handleCallback(req, res, (err, user) => {
        if (err) {
            return res.status(500).send(`认证回调出错:${err.message}`);
        }
        // 重定向回Bot聊天窗口
        res.redirect(`https://webchat.botframework.com/redirect?state=${req.query.state}`);
    });
});

server.listen(process.env.PORT || 3978, () => {
    console.log('Bot服务器已启动');
});

二、更现代的替代方案:使用Bot Framework v4的OAuthPrompt

如果你用的是Bot Framework v4+(现在推荐的版本),BotAuth其实已经有点过时了,官方提供的OAuthPrompt是更合适的选择,它原生支持自定义OAuth2提供商:

1. 配置自定义连接

你可以在Bot Framework Portal的「连接设置」里添加自定义OAuth2连接,填写第三方API的:

  • 授权端点URL
  • Token端点URL
  • Client ID/Secret
  • 权限范围等信息

2. 在对话中使用OAuthPrompt

const { ActivityHandler, OAuthPrompt, WaterfallDialog, DialogSet } = require('botbuilder');

class CustomAuthBot extends ActivityHandler {
    constructor(conversationState, userState) {
        super();
        this.conversationState = conversationState;
        this.userState = userState;
        this.dialogState = this.conversationState.createProperty('DialogState');
        this.dialogs = new DialogSet(this.dialogState);

        // 添加OAuthPrompt,指定自定义连接名称
        this.dialogs.add(new OAuthPrompt('CustomAuthPrompt', {
            connectionName: 'YourCustomOAuthConnection',
            text: '请登录你的自定义账号',
            title: '自定义账号登录',
            timeout: 300000 // 5分钟超时
        }));

        // 添加瀑布对话处理认证流程
        this.dialogs.add(new WaterfallDialog('LoginDialog', [
            async (step) => {
                // 触发登录提示
                return await step.beginDialog('CustomAuthPrompt');
            },
            async (step) => {
                const tokenResponse = step.result;
                if (tokenResponse) {
                    await step.context.sendActivity('登录成功!');
                    // 使用tokenResponse.token调用第三方API
                    const apiResponse = await fetch('https://your-custom-api.com/data', {
                        headers: { 'Authorization': `Bearer ${tokenResponse.token}` }
                    });
                    const data = await apiResponse.json();
                    await step.context.sendActivity(`获取到的数据:${JSON.stringify(data)}`);
                } else {
                    await step.context.sendActivity('登录失败,请重试。');
                }
                return await step.endDialog();
            }
        ]));

        // 处理用户消息
        this.onMessage(async (context, next) => {
            const dc = await this.dialogs.createContext(context);
            if (context.activity.text.includes('登录')) {
                await dc.beginDialog('LoginDialog');
            } else {
                await context.sendActivity('输入「登录」开始认证流程');
            }
            await this.conversationState.saveChanges(context);
            await next();
        });
    }
}

module.exports.CustomAuthBot = CustomAuthBot;

这种方式不需要自己封装提供商类,直接通过配置连接就能实现自定义认证,而且完全贴合Bot Framework的最新生态,维护性更好。

内容的提问来源于stack exchange,提问作者prtdomingo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:51:18