初衷

alist被卖了,原本使用的https://alist.nn.ci/tool/onedrive/callback已经不再安全了,万一收购alist的煞笔公司留了后门保存了你的授权信息,那你的od就完全是别人的玩具了,所以我打算自建。

由于我个人只使用od,只给出获取od刷新令牌的方法。国内的辣鸡网盘没有隐私而言,也没有api给你用,可谓是纯纯答辩,我也只是个废物小白,这个获取刷新令牌的网站完全依靠GPT生成,有需要其他网盘的自己折腾GPT去吧,我估计只要是官方给了api的基本都不会太难搞。

已建成示例(可正常使用)

挂载OneDrive

访问Get OneDrive Refresh Token

将你注册应用的Client IDClient Secret填入,跳转授权后即可返回Refresh Token,和原版官方的使用方法一模一样。

你唯一要做的变动是,alist存储设置里,回调url要填写网站里第三行显示的https://odoauth.shinoaa.com/onedrive/callback

挂载SharePoint

需要获取site id,这个自己手动获取一下,我没整出来。

首先访问你自己的site,例如https://companyname.sharepoint.com/sites/alist,然后在该url后面添加/_api/site/id进行访问,也就是访问https://companyname.sharepoint.com/sites/alist/_api/site/id,找到Edm.Guid后面的一串,那个就是site id

参考微软社区提问What is the best way to findout the Share Point Site ID and the Resource ID?

不过不能直接用,需要在前面添加上你的companyname,才能填入alist存储设置的site id里,类似于

1
companyname.sharepoint.com,1a2b3c4d-1234-4321-2333-1234567890ab

注意是半角逗号

具体代码及自建方法

前端

点击展开index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OneDrive Refresh Token 工具</title>
<style>
body { font-family: sans-serif; padding: 2rem; max-width: 600px; margin: auto; }
label { display: block; margin-top: 1rem; font-weight: bold; }
input, button { width: 100%; padding: 0.5rem; margin-top: 0.5rem; }
textarea { width: 100%; height: 100px; margin-top: 1rem; }
</style>
</head>
<body>
<h2>获取 OneDrive Refresh Token</h2>
<label for="client_id">Client ID</label>
<input type="text" id="client_id" placeholder="Azure 应用 Client ID" required />

<label for="client_secret">Client Secret</label>
<input type="text" id="client_secret" placeholder="Azure 应用 Client Secret" required />

<label for="redirect_uri">Redirect URI</label>
<input
type="text"
id="redirect_uri"
value="https://odoauth.shinoaa.com/onedrive/callback"
placeholder="例如: https://odoauth.shinoaa.com/onedrive/callback"
required
/>

<button onclick="startAuth()">跳转授权</button>

<script>
function startAuth() {
const clientId = document.getElementById('client_id').value.trim();
const clientSecret = document.getElementById('client_secret').value.trim();
const redirectUri = document.getElementById('redirect_uri').value.trim();

if (!clientId || !clientSecret || !redirectUri) {
alert('请填写 Client ID、Client Secret 和 Redirect URI');
return;
}

// 把敏感参数放入state,回调时后端解析
const stateObj = {
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri
};

const state = encodeURIComponent(JSON.stringify(stateObj));
const scope = encodeURIComponent('offline_access Files.ReadWrite.All');

const authUrl = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${encodeURIComponent(clientId)}&response_type=code&redirect_uri=${encodeURIComponent(redirectUri)}&response_mode=query&scope=${scope}&state=${state}`;

window.location.href = authUrl;
}
</script>
</body>
</html>

后端

点击展开index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const qs = require('querystring');

const app = express();
const port = process.env.PORT || 3010;

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

// 回调处理
app.get('/onedrive/callback', async (req, res) => {
const code = req.query.code;
const state = JSON.parse(decodeURIComponent(req.query.state || '{}'));

const client_id = state.client_id;
const client_secret = state.client_secret;
const redirect_uri = state.redirect_uri;

if (!code || !client_id || !client_secret || !redirect_uri) {
return res.status(400).send('缺少参数。');
}

const token_url = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';

const data = {
client_id,
client_secret,
code,
redirect_uri,
grant_type: 'authorization_code',
};

try {
const response = await axios.post(token_url, qs.stringify(data), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});

const token_data = response.data;

res.send(`
<h2>✅ 成功获取 Refresh Token</h2>
<p><strong>请妥善保存,仅展示一次:</strong></p>
<textarea rows="10" cols="80" readonly>${token_data.refresh_token}</textarea>
<p>access_token 也在响应中,但仅供临时使用</p>
`);
} catch (err) {
console.error(err?.response?.data || err);
res.status(500).send(`<h2>❌ 获取失败</h2><pre>${JSON.stringify(err.response?.data || err.message, null, 2)}</pre>`);
}
});

app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});

使用方法

此处使用aapanel建站,方便配置和申请SSL,手写Nginx配置文件大佬勿喷。

首先建个空的网站,做好解析和SSLSSL是必须的,因为微软回调url强制要求https

然后你需要在网站下建立如下拓扑结构,以下示例网站域名均为odoauth.shinoaa.com,自建的时候替换成你自己的

1
2
3
4
5
odoauth.shinoaa.com/
├── index.html
├── backend/
│ ├── index.js
│ └── .env

两个index上面都有,.env里写一行PORT=3010就行了,可以根据自己需求改端口。

如果.env文件不存在,默认使用3010端口,存在则以.env里写的为准。

然后开始配置Node.js环境。不要傻不拉几用原生apt源里的,版本太低了。我自己用的v18

1
2
3
4
5
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
cd /www/wwwroot/odoauth.shinoaa.com/backend
npm init -y
npm install dotenv express body-parser axios querystring @azure/msal-node

配置好环境后把给后端新建一个service

vim /etc/systemd/system/odoauth.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Unit]
Description=OneDrive OAuth Redirect Server
After=network.target

[Service]
Type=simple
WorkingDirectory=/www/wwwroot/odoauth.shinoaa.com/backend
ExecStart=/usr/bin/node /www/wwwroot/odoauth.shinoaa.com/backend/index.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
User=www-data
Group=www-data

# 限制文件描述符数目,避免意外问题
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

工作路径记得替换,手动安装Nginx的记得修改用户和组为rootaapanel用户不用改

启动odoauth.service

1
2
3
4
sudo systemctl daemon-reload
sudo systemctl enable odoauth.service
sudo systemctl start odoauth.service
sudo systemctl status odoauth.service

如果没启动,手动用/usr/bin/node index.js瞅一眼啥报错,有问题自己问GPT

最后一步配置反相代理,看不到代理目錄配置项的话记得点开高級功能

1
2
3
代理目錄	/onedrive/
目標 URL http://127.0.0.1:3010
發送域名 $host

手动安装Nginx参考反代配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#PROXY-START/

location ^~ /onedrive/
{
proxy_pass http://127.0.0.1:3010;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
# proxy_hide_header Upgrade;
#Persistent connection related configuration

add_header X-Cache $upstream_cache_status;
#Set Nginx Cache

set $static_filec1B5yAss 0;
if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" )
{
set $static_filec1B5yAss 1;
expires 1m;
}
if ( $static_filec1B5yAss = 0 )
{
add_header Cache-Control no-cache;
}
}
#PROXY-END/