React Native集成Twilio视频通话遇Invalid Access Token错误求助
我用React Native开发视频通话应用,已成功生成Access Token,但尝试建立视频通话时抛出错误:
ERROR: {"error": "Invalid Access Token issuer/subject", "roomName": "my_room", "roomSid": ""}
当前环境:
- twilio版本:^3.56.0
- react-native-twilio-video-webrtc:最新版本
App.js代码
import React, { Component } from "react"; import { StyleSheet, Text, TextInput, View, Button, TouchableOpacity, Platform, } from "react-native"; import { TwilioVideoLocalView, TwilioVideoParticipantView, TwilioVideo, } from "react-native-twilio-video-webrtc"; class App extends Component { state = { isAudioEnabled: true, isVideoEnabled: true, status: "disconnected", participants: new Map(), videoTracks: new Map(), roomName: "my_room", token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJZU0s3NGIyMGFmMWMwNGYyNzg2OTBhNDA4MDkyMGRjNTY2OC0xNjg0NTc3NDU3IiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoidGVzdCIsInZpZGVvIjp7InJvb20iOiJteV9yb29tIn19LCJpYXQiOjE2ODQ1Nzc0NTcsImV4cCI6MTY4NDU4MTA1NywiaXNzIjoiWVNLNzRiMjBhZjFjMDRmMjc4NjkwYTQwODA5MjBkYzU2NjgiLCJzdWIiOiJBQzA4NTVmY2Q5MGVhNzc0NjA2NzI2NGY1ZTFiMzhlNjNjIn0.ONkDw-6X5MtaCVmSiZAFknIflt4zRA-6oP7zA1Nxt14", }; _onConnectButtonPress = () => { try { this.twilioRef.connect({ roomName: this.state.roomName, accessToken: this.state.token, }); } catch (error) { console.log(error); } this.setState({ status: "connecting" }); }; _onEndButtonPress = () => { this.twilioRef.disconnect(); }; _onMuteButtonPress = () => { this.twilioRef .setLocalAudioEnabled(!this.state.isAudioEnabled) .then((isEnabled) => this.setState({ isAudioEnabled: isEnabled })); }; _onFlipButtonPress = () => { this.twilioRef.flipCamera(); }; _onRoomDidConnect = () => { this.setState({ status: "connected" }); }; _onRoomDidDisconnect = ({ roomName, error }) => { console.log("ERROR: ", error); this.setState({ status: "disconnected" }); }; _onRoomDidFailToConnect = (error) => { console.log("ERROR: ", error); this.setState({ status: "disconnected" }); }; _onParticipantAddedVideoTrack = ({ participant, track }) => { console.log("onParticipantAddedVideoTrack: ", participant, track); this.setState({ videoTracks: new Map([ ...this.state.videoTracks, [ track.trackSid, { participantSid: participant.sid, videoTrackSid: track.trackSid }, ], ]), }); }; _onParticipantRemovedVideoTrack = ({ participant, track }) => { console.log("onParticipantRemovedVideoTrack: ", participant, track); const videoTracks = this.state.videoTracks; videoTracks.delete(track.trackSid); this.setState({ videoTracks: new Map([...videoTracks]) }); }; setTwilioRef = (ref) => { this.twilioRef = ref; }; render() { return ( <View style={styles.container}> {this.state.status === "disconnected" && ( <View> <Text style={styles.welcome}>React Native Twilio Webrtc</Text> <TextInput style={styles.input} autoCapitalize="none" value={this.state.roomName} onChangeText={(text) => this.setState({ roomName: text })} ></TextInput> <TextInput style={styles.input} autoCapitalize="none" value={this.state.token} onChangeText={(text) => this.setState({ token: text })} ></TextInput> <Button title="Connect" style={styles.button} onPress={this._onConnectButtonPress} ></Button> </View> )} {this.state.status === "connected" || this.state.status === "connecting" ? ( <View style={styles.callContainer}> {this.state.status === "connected" && ( <View style={styles.remoteGrid}> {Array.from( this.state.videoTracks, ([trackSid, trackIdentifier]) => { return ( <TwilioVideoParticipantView style={styles.remoteVideo} key={trackSid} trackIdentifier={trackIdentifier} /> ); } )} </View> )} <View style={styles.optionsContainer}> <TouchableOpacity style={styles.optionButton} onPress={this._onEndButtonPress} > <Text style={{ fontSize: 12 }}>End</Text> </TouchableOpacity> <TouchableOpacity style={styles.optionButton} onPress={this._onMuteButtonPress} > <Text style={{ fontSize: 12 }}> {this.state.isAudioEnabled ? "Mute" : "Unmute"} </Text> </TouchableOpacity> <TouchableOpacity style={styles.optionButton} onPress={this._onFlipButtonPress} > <Text style={{ fontSize: 12 }}>Flip</Text> </TouchableOpacity> <TwilioVideoLocalView enabled={true} style={styles.localVideo} /> <View /> </View> </View> ) : null} <TwilioVideo ref={this.setTwilioRef} onRoomDidConnect={this._onRoomDidConnect} onRoomDidDisconnect={this._onRoomDidDisconnect} onRoomDidFailToConnect={this._onRoomDidFailToConnect} onParticipantAddedVideoTrack={this._onParticipantAddedVideoTrack} onParticipantRemovedVideoTrack={this._onParticipantRemovedVideoTrack} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "white", }, callContainer: { flex: 1, position: "absolute", bottom: 0, top: 0, left: 0, right: 0, }, welcome: { fontSize: 30, textAlign: "center", paddingTop: 40, }, input: { height: 50, borderWidth: 1, marginRight: 70, marginLeft: 70, marginTop: 50, textAlign: "center", backgroundColor: "white", }, button: { marginTop: 100, }, localVideo: { flex: 1, width: 125, height: 200, position: "absolute", right: 10, bottom: 400, borderRadius: 2, borderColor: "#4e4e4e", }, remoteGrid: { flex: 1, flexDirection: "row", flexWrap: "wrap", }, remoteVideo: { width: "100%", height: "100%", }, optionsContainer: { position: "absolute", left: 0, bottom: 0, right: 0, height: 100, flexDirection: "row", alignItems: "center", justifyContent: "center", }, optionButton: { width: 60, height: 60, marginLeft: 10, marginRight: 10, borderRadius: 100 / 2, backgroundColor: "grey", justifyContent: "center", alignItems: "center", }, }); export default App;
Token生成代码
const twilio = require("twilio"); const token = async () => { const accountSid = ""; const apiKeySid = ""; const apiKeySecret = ""; const AccessToken = twilio.jwt.AccessToken; const VideoGrant = AccessToken.VideoGrant; const token = new AccessToken(accountSid, apiKeySid, apiKeySecret); token.identity = "test"; const videoGrant = new VideoGrant({ room: "my_room" }); token.addGrant(videoGrant); token.ttl = 3600; console.log(token.toJwt()); }; token();
问题原因及解决办法
这个错误是因为Token的签发者(iss)或主题(sub)验证失败,核心原因是Token生成时使用的API Key、Account SID不匹配,或者没有正确配置权限。
验证账号信息正确性
确保accountSid是Twilio账户主SID(格式为AC开头),apiKeySid和apiKeySecret是从Twilio控制台创建的视频专用API Key,不能用主账户Auth Token替代,且API Key已启用视频服务权限。核对Token字段一致性
你提供的Token中,iss为YSK74b20af1c04f278690a4080920dc5668(对应API Key Sid),sub为AC0855fcd90ea7746067264f5e1b38e63c(对应Account SID),要确保这两个值和生成Token时填写的apiKeySid、accountSid完全一致,无拼写错误。升级Twilio库版本
twilio@3.56.0版本较旧,存在Token生成逻辑兼容性问题,建议升级到最新稳定版:npm install twilio@latest确认房间配置
确保要加入的my_room存在,或Twilio控制台设置为允许自动创建房间;同时保证Token中VideoGrant的房间名和App中roomName完全一致。重新生成Token
修正上述问题后,重新运行Token生成代码,用新Token替换App中的旧Token再尝试连接。
内容的提问来源于stack exchange,提问作者Meer Suhana

