Skip to content

Commit 865d2f9

Browse files
JacobCoffeeclaude
andcommitted
fix: oauth callback postMessage for Sveltia CMS compatibility
Support both Sveltia CMS protocol (parent sends authorizing:github to popup) and Decap CMS protocol (popup notifies parent first). Also handle GitHub rejecting reused auth codes gracefully instead of 500ing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 94cece1 commit 865d2f9

1 file changed

Lines changed: 21 additions & 8 deletions

File tree

oauth/app.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,23 @@
3535
(function() {
3636
const token = "%s";
3737
const data = JSON.stringify({token: token, provider: "github"});
38+
const msg = "authorization:github:success:" + data;
3839
39-
// Sveltia/Decap CMS sends "authorizing:github" to the popup;
40-
// the popup replies with the token and closes itself.
40+
function sendToken(origin) {
41+
window.opener.postMessage(msg, origin || "*");
42+
window.close();
43+
}
44+
45+
// Listen for "authorizing:github" from the parent (Sveltia CMS protocol)
4146
window.addEventListener("message", function(e) {
4247
if (e.data === "authorizing:github") {
43-
window.opener.postMessage(
44-
"authorization:github:success:" + data,
45-
e.origin
46-
);
47-
window.close();
48+
sendToken(e.origin);
4849
}
4950
}, false);
51+
52+
// Also notify the parent we're ready (Decap CMS protocol),
53+
// which triggers it to send "authorizing:github" back to us.
54+
window.opener.postMessage("authorizing:github", "*");
5055
})();
5156
</script></body></html>
5257
"""
@@ -94,7 +99,15 @@ async def callback(code: str) -> ASGIResponse:
9499
headers={"Accept": "application/json"},
95100
)
96101
resp.raise_for_status()
97-
token = resp.json()["access_token"]
102+
body = resp.json()
103+
token = body.get("access_token")
104+
if not token:
105+
error = body.get("error_description", body.get("error", "unknown error"))
106+
return ASGIResponse(
107+
body=f"OAuth token exchange failed: {error}".encode(),
108+
media_type="text/plain",
109+
status_code=400,
110+
)
98111
return ASGIResponse(body=(CALLBACK_HTML % token).encode(), media_type="text/html")
99112

100113

0 commit comments

Comments
 (0)