如何自动刷新 Instagram Basic Display API 令牌?
How to refresh Instagram Basic Display API token automatically?
我正在尝试为我的 Nextjs 应用设置一个 public instagram 帐户的 instagram 提要(只有图像和链接)。
我知道我需要使用 Instagram Basic Display API and get a Long-Lived Access Token,但它会在 60 天后过期,我不想手动刷新它。有谁知道自动执行此操作的好方法,最好是免费的?
我看过 instagram-token-agent,但该设置使用 Heroku 和一个每月花费 30 美元的附加组件,这似乎很高。
任何想法或链接都会很有帮助,谢谢!
我最终使用了 Google Cloud Secret Manager。
概述:Secret Manager 存储长寿命令牌,每次轮换都会触发 pub/sub,然后触发云函数。云函数为新令牌刷新令牌,然后将新版本添加到机密中。
将其命名为“instagram-token”并添加您长期存在的令牌作为秘密值。现在保留所有其他默认设置并创建秘密。
Create a service account for secret manager
在您的终端中:
gcloud auth login
然后
gcloud beta services identity create --service "secretmanager.googleapis.com" --project "YOUR_GCP_PROJECT_ID"
它可能会要求您安装 gcloud beta 命令。
重要提示:确保记下终端中返回的服务帐户的全名。如果丢失了,运行 再次执行相同的命令。
创建一个新主题并将其命名为“instagram-token-refresh”,取消勾选'add a default subscription'。
Give secret manager permission to publish pub/sub
在您的新 pub/sub 主题中,转到权限 -> 添加原则。
搜索并添加上面添加的服务帐户名称。服务-{id}@gcp-sa-secretmanager.iam.gserviceaccount.com。添加新角色 Pub/Sub 发布者
Add rotation and pub/sub to secret
- 转到您的“instagram-token”秘密并“编辑秘密”。
- 轮换 -> 自定义 -> 每 50 天
- 通知 -> 添加主题 -> Select“instagram-token-refresh”
- 保存
现在每 50 天您的“instagram-token-refresh”pub/sub 将被触发。
创建云函数
- 搜索云函数 -> 启用 -> 创建云函数
- 函数名称:“Refresh-Instagram-Token”
- 触发器:pub/sub -> Select“instagram-token-refresh”
- 点击下一步
- 入口点:“refreshInstaToken”
- 编辑文件:
您可能需要启用云构建 API
package.json
{
"name": "refresh-instagram-token",
"version": "0.0.1",
"dependencies": {
"@google-cloud/pubsub": "^0.18.0",
"@google-cloud/secret-manager": "^3.10.1",
"axios": "^0.24.0"
}
}
index.js
// Import the Secret Manager client
const { SecretManagerServiceClient } = require("@google-cloud/secret-manager");
const axios = require('axios');
// name of function is the same as entry point
exports.refreshInstaToken = async (event, context) => {
// check pub/sub message is rotation to prevent infinte looping
const event_type = event && event.attributes.eventType;
//allowing SECRET_VERSION_ENABLE lets you manually trigger this function by disabling the secret and then enabling it (rather than waiting for rotation trigger)
if (event_type != "SECRET_ROTATE" && event_type != "SECRET_VERSION_ENABLE") {
return null;
}
// secret name
const parent = event.attributes.secretId;
const name = parent + "/versions/latest";
// Instantiates a client
const client = new SecretManagerServiceClient();
// get latest secret
const [version] = await client.accessSecretVersion({
name: name,
});
// Extract the payload as a string.
const secret = version.payload.data.toString();
// refresh token
const requesturl = `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${secret}`;
const response = await axios.get(requesturl);
const data = await response.data;
// data = {"access_token", "token_type", "expires_in"}
// check access_token isn't null
if (data && data.access_token) {
// Payload is the plaintext data to store in the secret
const newSecret = Buffer.from(data.access_token, "utf8");
// add new secret version (the refreshed token)
const [newVersion] = await client.addSecretVersion({
parent: parent,
payload: {
data: newSecret,
},
});
console.log(`Added new secret version ${newVersion.name}`);
// get new secret version number
let newVersionN = newVersion.name.split("/");
newVersionN = newVersionN[newVersionN.length - 1];
if (newVersionN > 1) {
// if is a second version delete one before it
const nameToDestroy = parent + "/versions/" + (newVersionN - 1);
const [deletedVersion] = await client.destroySecretVersion({
name: nameToDestroy,
});
console.info(`Destroyed ${deletedVersion.name}`);
}
}
};
Consume event notifications with Cloud Functions Ref
将云函数权限授予 Secret
- 转到您的秘密 -> 权限
- 添加 -> {project-id}@appspot.gserviceaccount.com
- 添加角色“Secret Manager Admin”
正在从服务帐户访问 Secret Manager
- 创建 new service account 名称“instagram-token”。
- 在新服务帐户中 -> 密钥 -> 添加密钥 -> 保存到桌面
- 转到您的秘密 -> 权限 -> 添加 -> “instagram-token...gserviceaccount.com”并赋予“Secret Manager Secret Accessor”角色
设置凭据环境变量
在下一个js根目录下创建.env.local文件
添加新的空值GOOGLE_APPLICATION_CREDENTIALS=
Convert JSON file to Base64 key and copy to clipboard MAC
openssl base64 < /Users/{username}/Desktop/service-account.json | tr -d '\n' | pbcopy
certutil -encode service-account.json encoded.txt
- 粘贴到变量,这样你就会得到类似
GOOGLE_APPLICATION_CREDENTIALS=faGdfdSytDsdcDg...
的内容
安装@google-cloud/secret-managernpm i @google-cloud/secret-manager
const {
SecretManagerServiceClient
} = require("@google-cloud/secret-manager");
export const getInstagramToken = async() => {
// parse your base 64 env variable to a JSON object
const credentials = JSON.parse(
Buffer.from(process.env.GOOGLE_APPLICATION_CREDENTIALS, "base64").toString()
);
// TO DO -> CHANGE
const projectId = "eleanor-daisy";
const secretId = "instagram-token";
// set up credentials config
const config = {
projectId,
credentials,
};
// init secret manager with credentials
const client = new SecretManagerServiceClient(config);
const secretName = `projects/${projectId}/secrets/${secretId}/versions/latest`;
// Access the secret.
const [accessResponse] = await client.accessSecretVersion({
name: secretName,
});
const instaToken = accessResponse.payload.data.toString("utf8");
return instaToken;
};
在部署时添加 GOOGLE_APPLICATION_CREDENTIALS 和 vercel 的密钥。
完成!我可能会为此制作一个视频教程,因为那里的内容不多,请告诉我这是否有帮助:)
我正在尝试为我的 Nextjs 应用设置一个 public instagram 帐户的 instagram 提要(只有图像和链接)。
我知道我需要使用 Instagram Basic Display API and get a Long-Lived Access Token,但它会在 60 天后过期,我不想手动刷新它。有谁知道自动执行此操作的好方法,最好是免费的?
我看过 instagram-token-agent,但该设置使用 Heroku 和一个每月花费 30 美元的附加组件,这似乎很高。
任何想法或链接都会很有帮助,谢谢!
我最终使用了 Google Cloud Secret Manager。
概述:Secret Manager 存储长寿命令牌,每次轮换都会触发 pub/sub,然后触发云函数。云函数为新令牌刷新令牌,然后将新版本添加到机密中。
将其命名为“instagram-token”并添加您长期存在的令牌作为秘密值。现在保留所有其他默认设置并创建秘密。
Create a service account for secret manager
在您的终端中:
gcloud auth login
然后
gcloud beta services identity create --service "secretmanager.googleapis.com" --project "YOUR_GCP_PROJECT_ID"
它可能会要求您安装 gcloud beta 命令。
重要提示:确保记下终端中返回的服务帐户的全名。如果丢失了,运行 再次执行相同的命令。
创建一个新主题并将其命名为“instagram-token-refresh”,取消勾选'add a default subscription'。
Give secret manager permission to publish pub/sub
在您的新 pub/sub 主题中,转到权限 -> 添加原则。 搜索并添加上面添加的服务帐户名称。服务-{id}@gcp-sa-secretmanager.iam.gserviceaccount.com。添加新角色 Pub/Sub 发布者
Add rotation and pub/sub to secret
- 转到您的“instagram-token”秘密并“编辑秘密”。
- 轮换 -> 自定义 -> 每 50 天
- 通知 -> 添加主题 -> Select“instagram-token-refresh”
- 保存
现在每 50 天您的“instagram-token-refresh”pub/sub 将被触发。
创建云函数
- 搜索云函数 -> 启用 -> 创建云函数
- 函数名称:“Refresh-Instagram-Token”
- 触发器:pub/sub -> Select“instagram-token-refresh”
- 点击下一步
- 入口点:“refreshInstaToken”
- 编辑文件:
您可能需要启用云构建 API
package.json
{
"name": "refresh-instagram-token",
"version": "0.0.1",
"dependencies": {
"@google-cloud/pubsub": "^0.18.0",
"@google-cloud/secret-manager": "^3.10.1",
"axios": "^0.24.0"
}
}
index.js
// Import the Secret Manager client
const { SecretManagerServiceClient } = require("@google-cloud/secret-manager");
const axios = require('axios');
// name of function is the same as entry point
exports.refreshInstaToken = async (event, context) => {
// check pub/sub message is rotation to prevent infinte looping
const event_type = event && event.attributes.eventType;
//allowing SECRET_VERSION_ENABLE lets you manually trigger this function by disabling the secret and then enabling it (rather than waiting for rotation trigger)
if (event_type != "SECRET_ROTATE" && event_type != "SECRET_VERSION_ENABLE") {
return null;
}
// secret name
const parent = event.attributes.secretId;
const name = parent + "/versions/latest";
// Instantiates a client
const client = new SecretManagerServiceClient();
// get latest secret
const [version] = await client.accessSecretVersion({
name: name,
});
// Extract the payload as a string.
const secret = version.payload.data.toString();
// refresh token
const requesturl = `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${secret}`;
const response = await axios.get(requesturl);
const data = await response.data;
// data = {"access_token", "token_type", "expires_in"}
// check access_token isn't null
if (data && data.access_token) {
// Payload is the plaintext data to store in the secret
const newSecret = Buffer.from(data.access_token, "utf8");
// add new secret version (the refreshed token)
const [newVersion] = await client.addSecretVersion({
parent: parent,
payload: {
data: newSecret,
},
});
console.log(`Added new secret version ${newVersion.name}`);
// get new secret version number
let newVersionN = newVersion.name.split("/");
newVersionN = newVersionN[newVersionN.length - 1];
if (newVersionN > 1) {
// if is a second version delete one before it
const nameToDestroy = parent + "/versions/" + (newVersionN - 1);
const [deletedVersion] = await client.destroySecretVersion({
name: nameToDestroy,
});
console.info(`Destroyed ${deletedVersion.name}`);
}
}
};
Consume event notifications with Cloud Functions Ref
将云函数权限授予 Secret
- 转到您的秘密 -> 权限
- 添加 -> {project-id}@appspot.gserviceaccount.com
- 添加角色“Secret Manager Admin”
正在从服务帐户访问 Secret Manager
- 创建 new service account 名称“instagram-token”。
- 在新服务帐户中 -> 密钥 -> 添加密钥 -> 保存到桌面
- 转到您的秘密 -> 权限 -> 添加 -> “instagram-token...gserviceaccount.com”并赋予“Secret Manager Secret Accessor”角色
设置凭据环境变量
在下一个js根目录下创建.env.local文件
添加新的空值
GOOGLE_APPLICATION_CREDENTIALS=
Convert JSON file to Base64 key and copy to clipboard MAC
openssl base64 < /Users/{username}/Desktop/service-account.json | tr -d '\n' | pbcopy
certutil -encode service-account.json encoded.txt
- 粘贴到变量,这样你就会得到类似
GOOGLE_APPLICATION_CREDENTIALS=faGdfdSytDsdcDg...
的内容
安装@google-cloud/secret-managernpm i @google-cloud/secret-manager
const {
SecretManagerServiceClient
} = require("@google-cloud/secret-manager");
export const getInstagramToken = async() => {
// parse your base 64 env variable to a JSON object
const credentials = JSON.parse(
Buffer.from(process.env.GOOGLE_APPLICATION_CREDENTIALS, "base64").toString()
);
// TO DO -> CHANGE
const projectId = "eleanor-daisy";
const secretId = "instagram-token";
// set up credentials config
const config = {
projectId,
credentials,
};
// init secret manager with credentials
const client = new SecretManagerServiceClient(config);
const secretName = `projects/${projectId}/secrets/${secretId}/versions/latest`;
// Access the secret.
const [accessResponse] = await client.accessSecretVersion({
name: secretName,
});
const instaToken = accessResponse.payload.data.toString("utf8");
return instaToken;
};
在部署时添加 GOOGLE_APPLICATION_CREDENTIALS 和 vercel 的密钥。
完成!我可能会为此制作一个视频教程,因为那里的内容不多,请告诉我这是否有帮助:)