移除钉钉通知网页授权兜底
This commit is contained in:
parent
b09241975c
commit
45284c3b9f
@ -4,11 +4,6 @@ import {
|
||||
getAuthSessionCookieCandidates,
|
||||
resolveSecureAuthCookieFromRequest,
|
||||
} from '@/lib/auth-cookie'
|
||||
import {
|
||||
DINGTALK_DIRECT_LOGIN_SOURCE,
|
||||
buildDingtalkOAuthUrl,
|
||||
} from '@/lib/dingtalk-oauth'
|
||||
import { getDingtalkWorkNoticeClientId } from '@/lib/dingtalk-client'
|
||||
import {
|
||||
getConfiguredDingtalkCorpId,
|
||||
normalizeDingtalkCorpId,
|
||||
@ -45,13 +40,9 @@ function stringifyForInlineScript(value: string) {
|
||||
function createH5LoginPage({
|
||||
redirectPath,
|
||||
corpId,
|
||||
clientId,
|
||||
fallbackOAuthUrl,
|
||||
}: {
|
||||
redirectPath: string
|
||||
corpId: string
|
||||
clientId: string
|
||||
fallbackOAuthUrl: string
|
||||
}) {
|
||||
return new NextResponse(
|
||||
`<!doctype html>
|
||||
@ -67,7 +58,6 @@ function createH5LoginPage({
|
||||
h1{margin:0 0 12px;font-size:22px}
|
||||
p{margin:0;color:#cbd5e1;line-height:1.7}
|
||||
.spinner{width:38px;height:38px;margin:0 auto 20px;border:4px solid rgba(255,255,255,.24);border-top-color:#60a5fa;border-radius:999px;animation:spin .85s linear infinite}
|
||||
a{color:#93c5fd}
|
||||
@keyframes spin{to{transform:rotate(360deg)}}
|
||||
</style>
|
||||
</head>
|
||||
@ -81,7 +71,6 @@ function createH5LoginPage({
|
||||
(function () {
|
||||
var target = ${stringifyForInlineScript(redirectPath)};
|
||||
var corpId = ${stringifyForInlineScript(corpId)};
|
||||
var fallbackOAuthUrl = ${stringifyForInlineScript(fallbackOAuthUrl)};
|
||||
var started = false;
|
||||
var status = document.getElementById('status');
|
||||
|
||||
@ -103,16 +92,6 @@ function createH5LoginPage({
|
||||
}
|
||||
}
|
||||
|
||||
function appendFallbackLink() {
|
||||
if (!status) return;
|
||||
status.appendChild(document.createElement('br'));
|
||||
status.appendChild(document.createElement('br'));
|
||||
var link = document.createElement('a');
|
||||
link.href = fallbackOAuthUrl;
|
||||
link.textContent = '改用网页授权登录';
|
||||
status.appendChild(link);
|
||||
}
|
||||
|
||||
function showError(message, detail) {
|
||||
if (status) {
|
||||
status.textContent = message + '。请返回钉钉重新打开通知,或联系管理员检查钉钉免登配置。';
|
||||
@ -120,30 +99,11 @@ function createH5LoginPage({
|
||||
status.appendChild(document.createElement('br'));
|
||||
status.appendChild(document.createTextNode('错误详情:' + String(detail).slice(0, 180)));
|
||||
}
|
||||
appendFallbackLink();
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackToOAuth(message, error) {
|
||||
var detail = stringifyError(error);
|
||||
console.log('DingTalk H5 login fallback:', message, detail || error || '');
|
||||
if (status) {
|
||||
status.textContent = message + '。可返回钉钉重新打开通知,或点击下方改用网页授权登录。';
|
||||
if (detail) {
|
||||
status.appendChild(document.createElement('br'));
|
||||
status.appendChild(document.createTextNode('错误详情:' + detail.slice(0, 180)));
|
||||
}
|
||||
appendFallbackLink();
|
||||
}
|
||||
}
|
||||
|
||||
window.__failDingtalkLogin = showError;
|
||||
|
||||
function completeProfile(user) {
|
||||
var userInfo = encodeURIComponent(JSON.stringify(user || {}));
|
||||
window.location.replace('/complete-profile?userInfo=' + userInfo);
|
||||
}
|
||||
|
||||
function submitCode(code) {
|
||||
setStatus('已获取钉钉身份,正在创建登录状态...');
|
||||
var form = document.createElement('form');
|
||||
@ -161,70 +121,6 @@ function createH5LoginPage({
|
||||
form.submit();
|
||||
}
|
||||
|
||||
function resolveAuthCode(result) {
|
||||
return result && (result.code || result.authCode || result.auth_code);
|
||||
}
|
||||
|
||||
function requestAuthCodeWithFallback(dd, previousError) {
|
||||
if (dd.getAuthCode) {
|
||||
setStatus('正在尝试钉钉新版免登接口...');
|
||||
try {
|
||||
var promiseResult = dd.getAuthCode({ corpId: corpId });
|
||||
if (promiseResult && typeof promiseResult.then === 'function') {
|
||||
promiseResult
|
||||
.then(function (result) {
|
||||
var code = resolveAuthCode(result);
|
||||
if (!code) {
|
||||
fallbackToOAuth('钉钉新版免登接口未返回授权码', result || previousError);
|
||||
return;
|
||||
}
|
||||
submitCode(code);
|
||||
})
|
||||
.catch(function (error) {
|
||||
fallbackToOAuth('钉钉免登授权失败', error || previousError);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var directCode = resolveAuthCode(promiseResult);
|
||||
if (directCode) {
|
||||
submitCode(directCode);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
fallbackToOAuth('钉钉免登授权失败', error || previousError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (dd.requestAuthCode) {
|
||||
setStatus('正在尝试钉钉备用免登接口...');
|
||||
try {
|
||||
dd.requestAuthCode({
|
||||
corpId: corpId,
|
||||
clientId: ${stringifyForInlineScript(clientId)},
|
||||
onSuccess: function (result) {
|
||||
var code = resolveAuthCode(result);
|
||||
if (!code) {
|
||||
fallbackToOAuth('钉钉备用免登接口未返回授权码', result || previousError);
|
||||
return;
|
||||
}
|
||||
submitCode(code);
|
||||
},
|
||||
onFail: function (error) {
|
||||
fallbackToOAuth('钉钉免登授权失败', error || previousError);
|
||||
}
|
||||
});
|
||||
return;
|
||||
} catch (error) {
|
||||
fallbackToOAuth('钉钉免登授权失败', error || previousError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fallbackToOAuth('钉钉免登授权失败', previousError);
|
||||
}
|
||||
|
||||
window.__startDingtalkLogin = function () {
|
||||
if (started) return;
|
||||
started = true;
|
||||
@ -232,19 +128,19 @@ function createH5LoginPage({
|
||||
|
||||
var dd = window.dd;
|
||||
if (!dd || !dd.ready || !dd.runtime || !dd.runtime.permission) {
|
||||
fallbackToOAuth('当前页面未检测到钉钉客户端环境');
|
||||
showError('当前页面未检测到钉钉客户端环境');
|
||||
return;
|
||||
}
|
||||
|
||||
var readyTimer = setTimeout(function () {
|
||||
fallbackToOAuth('钉钉免登初始化超时');
|
||||
showError('钉钉免登初始化超时');
|
||||
}, 15000);
|
||||
|
||||
if (dd.error) {
|
||||
dd.error(function (error) {
|
||||
console.log('DingTalk JSAPI error:', error);
|
||||
clearTimeout(readyTimer);
|
||||
fallbackToOAuth('钉钉免登初始化失败', error);
|
||||
showError('钉钉免登初始化失败', stringifyError(error));
|
||||
});
|
||||
}
|
||||
|
||||
@ -262,45 +158,28 @@ function createH5LoginPage({
|
||||
},
|
||||
onFail: function (error) {
|
||||
console.log('requestAuthCode failed:', error);
|
||||
requestAuthCodeWithFallback(dd, error);
|
||||
showError('钉钉免登授权失败', stringifyError(error));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
setStatus('正在加载钉钉免登组件...');
|
||||
var scriptUrls = [
|
||||
'https://g.alicdn.com/dingding/dingtalk-jsapi/3.0.12/dingtalk.open.js',
|
||||
'https://g.alicdn.com/dingding/dingtalk-jsapi/3.0.39/dingtalk.open.js',
|
||||
'https://g.alicdn.com/dingding/dingtalk-jsapi/3.0.36/dingtalk.open.js'
|
||||
];
|
||||
var scriptIndex = 0;
|
||||
var loadTimer = setTimeout(function () {
|
||||
if (!started) fallbackToOAuth('钉钉免登组件加载超时');
|
||||
if (!started) showError('钉钉免登组件加载超时');
|
||||
}, 15000);
|
||||
|
||||
function loadDingtalkScript() {
|
||||
var script = document.createElement('script');
|
||||
script.src = scriptUrls[scriptIndex];
|
||||
script.onload = function () {
|
||||
clearTimeout(loadTimer);
|
||||
if (window.__startDingtalkLogin) window.__startDingtalkLogin();
|
||||
};
|
||||
script.onerror = function () {
|
||||
scriptIndex += 1;
|
||||
if (scriptIndex < scriptUrls.length) {
|
||||
setStatus('钉钉免登组件加载失败,正在尝试备用版本...');
|
||||
loadDingtalkScript();
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(loadTimer);
|
||||
fallbackToOAuth('钉钉 JSAPI 加载失败');
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
loadDingtalkScript();
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://g.alicdn.com/dingding/dingtalk-jsapi/3.0.39/dingtalk.open.js';
|
||||
script.onload = function () {
|
||||
clearTimeout(loadTimer);
|
||||
if (window.__startDingtalkLogin) window.__startDingtalkLogin();
|
||||
};
|
||||
script.onerror = function () {
|
||||
clearTimeout(loadTimer);
|
||||
showError('钉钉 JSAPI 加载失败');
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
@ -314,6 +193,38 @@ function createH5LoginPage({
|
||||
)
|
||||
}
|
||||
|
||||
function createDingtalkOnlyPage() {
|
||||
return new NextResponse(
|
||||
`<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>请在钉钉内打开</title>
|
||||
<style>
|
||||
body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;background:#0f172a;color:#f8fafc;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
|
||||
main{width:min(420px,calc(100vw - 48px));padding:32px 24px;text-align:center}
|
||||
h1{margin:0 0 12px;font-size:22px}
|
||||
p{margin:0;color:#cbd5e1;line-height:1.7}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>请在钉钉内打开</h1>
|
||||
<p>考核调研通知链接需要在钉钉客户端内确认身份。</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>`,
|
||||
{
|
||||
status: 403,
|
||||
headers: {
|
||||
'Content-Type': 'text/html; charset=utf-8',
|
||||
'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0',
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
function createMissingCorpIdPage() {
|
||||
return new NextResponse(
|
||||
`<!doctype html>
|
||||
@ -354,15 +265,8 @@ export async function GET(request: NextRequest) {
|
||||
return NextResponse.redirect(new URL(redirectPath, getPublicAppOrigin()))
|
||||
}
|
||||
|
||||
const fallbackOAuthUrl = buildDingtalkOAuthUrl({
|
||||
redirectPath,
|
||||
callbackPath: '/api/dingtalk/callback',
|
||||
clientId: getDingtalkWorkNoticeClientId(),
|
||||
source: DINGTALK_DIRECT_LOGIN_SOURCE,
|
||||
})
|
||||
|
||||
if (!isDingtalkBrowser(request)) {
|
||||
return NextResponse.redirect(fallbackOAuthUrl)
|
||||
return createDingtalkOnlyPage()
|
||||
}
|
||||
|
||||
const queryCorpId =
|
||||
@ -377,7 +281,5 @@ export async function GET(request: NextRequest) {
|
||||
return createH5LoginPage({
|
||||
redirectPath,
|
||||
corpId,
|
||||
clientId: getDingtalkWorkNoticeClientId(),
|
||||
fallbackOAuthUrl,
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user