我正在构建一个示例 ReactJS + Vite 应用程序,使用 oidc-client-ts 库实现 OAuth2/OIDC 流 和 DPoP,并且从 文档 我看到要实例化一个 UserManager 对象我' d 必须按照以下方式做一些事情
import { UserManager } from 'oidc-client-ts';
const settings = {
authority: 'https://demo.identityserver.io',
client_id: 'interactive.public',
redirect_uri: 'http://localhost:8080',
response_type: 'code',
scope: 'openid profile email api',
post_logout_redirect_uri: 'http://localhost:8080',
userStore: new WebStorageStateStore({ store: window.localStorage }),
dpop: {
bind_authorization_code: true,
store: new IndexedDbDPoPStore()
}
};
const userManager = new UserManager(settings);
问题是,每次组件需要使用 UserManager 对象时,都会生成一个新的 IndexedDbDPoPStore。再加上我需要以编程方式生成私钥/公钥对以将访问令牌绑定到公钥这一事实,还会在新存储旁边生成一个新的密钥对。 当有人刷新需要使用 UserManager 的组件上的页面并进行 REST API 调用时,这会导致问题,因为 DPoPproof 将使用新创建的私钥而不是原始私钥生成。 有没有办法防止 UserManager 被多次创建? 我正在考虑一个全局变量,但我不知道这是否是正确的解决方案。 谢谢
免责声明:这仅有效,因为 oidc-client-ts 库使用代码中指定的值(“oidc”和“dpop”)。未来版本中对它们的任何更改都可能导致所提供代码的功能丧失。如果不再使用 IndexedDB 来依赖私钥/公钥存储,这也适用。
const dbName = 'oidc'
const objectName = 'dpop'
const clientID = 'yourClientID'
async function checkIndexedDbDPoPStore() {
return new Promise((resolve, reject) => {
const req = indexedDB.open(dbName);
req.onsuccess = (event) => {
const db = event.target.result;
if (db.objectStoreNames.contains(objectName)) {
const transaction = db.transaction([objectName], 'readonly');
const objectStore = transaction.objectStore(objectName);
const getRequest = objectStore.get(clientID);
getRequest.onsuccess = () => {
if (getRequest.result) {
resolve(db);
} else {
db.close();
resolve(null);
}
};
getRequest.onerror = () => {
db.close();
reject('Error retrieving ' + clientID + ' from IndexedDB');
};
} else {
db.close();
resolve(null);
}
};
req.onerror = () => {
reject('Error opening IndexedDB');
};
req.onupgradeneeded = (event) => {
event.target.transaction.abort();
resolve(null);
};
});
}
如果发生 onupgradeneeded 事件,中止事务非常重要。