diff --git a/HTML/setting.html b/HTML/setting.html index bb205b8..b99464a 100644 --- a/HTML/setting.html +++ b/HTML/setting.html @@ -21,7 +21,7 @@

Login to Bluesky

- +

OK

diff --git a/JS/BlueskyAPI.js b/JS/BlueskyAPI.js index 4db456a..d8d0305 100644 --- a/JS/BlueskyAPI.js +++ b/JS/BlueskyAPI.js @@ -4,7 +4,6 @@ export async function GetBlueskyDID(PDS, Handle) { return request; } - // Component 1/4 export async function GetPDSWellKnown() { let Data = await fetch("https://bsky.social/.well-known/oauth-authorization-server", {method: "GET"}) @@ -37,15 +36,11 @@ export async function CreatePKCECodeChallenge(CodeVerifier) { // Component 3/4 export async function PARrequest(PAREndpoint, State, ChallengeCode) { - return await fetch(PAREndpoint, {method: "POST", body: new URLSearchParams({ response_type: "code", code_challenge_method: "S256", scope: "atproto transition:generic", client_id: "https://fedi.crowdedgames.group/oauth/client-metadata.json", redirect_uri: "https://fedi.crowdedgames.group/HTML/mail.html", code_challenge: ChallengeCode, state: State, login_hint: "crowdedgames.group" }), "Content-Type": "application/x-www-form-urlencoded"}) - .then(function(response) { - console.log(response.headers.get("dpop-nonce")); - return response.json(); - }); + return fetch(PAREndpoint, {method: "POST", body: new URLSearchParams({ response_type: "code", code_challenge_method: "S256", scope: "atproto transition:generic", client_id: "https://fedi.crowdedgames.group/oauth/client-metadata.json", redirect_uri: "https://fedi.crowdedgames.group/HTML/setting.html", code_challenge: ChallengeCode, state: State, login_hint: "crowdedgames.group" }), "Content-Type": "application/x-www-form-urlencoded"}); } // Component 4/4 -export async function ClientDPoP(POSTorGET, RequestURL, DPoPNonce) { +export async function ClientDPoP(POSTorGET, RequestURL, DPoPNonce, publicKey) { let KeyPair = await crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]); // Header @@ -83,9 +78,39 @@ export async function AssertionJWT() { var sHeader = JSON.stringify(Header); var sPayload = JSON.stringify(Payload); var JWT = KJUR.jws.JWS.sign("HS256", sHeader, sPayload, "838383"); - console.log(JWT); - console.log(KeyPair.publicKey); - console.log(KeyPair.privateKey); +} + +export async function HandleAuthorization(BlueskyPKCEverifer, BlueskyPKCEchallenge, BlueskyNonce) { + // Declare Variables + let KeyPair = await crypto.subtle.generateKey({name: "ECDSA", namedCurve: "P-256"}, true, ["sign", "verify"]); + + let WellKnown = await GetPDSWellKnown(); + let PAREndpoint = WellKnown.pushed_authorization_request_endpoint; + + let State = GenerateToken(64); + + let PKCEverifier = await CreatePKCECodeVerifier(); + let PKCEchallenge = await CreatePKCECodeChallenge(PKCEverifier); + // PAR request (beginning) + let PAR = PARrequest(WellKnown.pushed_authorization_request_endpoint, State, PKCEchallenge); + let body = await PAR.then((response) => response.json()); + let nonce = await PAR.then((response) => response.headers.get("dpop-nonce")); + + let ExportedKey1 = await crypto.subtle.exportKey("raw", KeyPair.publicKey); + // Save these things. + document.cookie = BlueskyPKCEverifer + "=" + PKCEverifier + ";samesite=strict;path=/;expires=Fri, 31 Dec 9999 23:59:59 GMT;"; + document.cookie = BlueskyPKCEchallenge + "=" + PKCEchallenge + ";samesite=strict;path=/;expires=Fri, 31 Dec 9999 23:59:59 GMT;"; + document.cookie = BlueskyNonce + "=" + nonce + ";samesite=strict;path=/;expires=Fri, 31 Dec 9999 23:59:59 GMT;"; + // Don't remove the keys. They are important. + // if (document.cookie.split("; ").find((row) => row.startsWith(BlueskyPublicKey + "="))?.split("=").length == 1 || document.cookie.split("; ").find((row) => row.startsWith(BlueskyPrivateKey + "="))?.split("=").length == 1) { + // document.cookie = BlueskyPublicKey + "=" + ExportedKey1 + ";samesite=strict;path=/;expires=Fri, 31 Dec 9999 23:59:59 GMT;"; + // } + // Now we need to authenticate. Make sure the State stays the same throughout this whole process :] + document.location.href = "https://bsky.social/oauth/authorize?client_id=https://fedi.crowdedgames.group/oauth/client-metadata.json&request_uri=" + body.request_uri; +} + +export async function GainTokens() { + } // Stolen from elsewhere. @@ -119,3 +144,4 @@ export function GenerateToken(length) { } return token; } + diff --git a/JS/mail.js b/JS/mail.js index e038497..86f3f02 100644 --- a/JS/mail.js +++ b/JS/mail.js @@ -15,7 +15,6 @@ let BlueskyApp = "https://bsky.app"; let BlueskyPDS = "https://bsky.social"; let BlueskyPKCEverifer = "bluesky_pkce_verifier"; let BlueskyPKCEchallenge = "bluesky_pkce_challenge"; -let BlueskyPrivateKey = "bluesky_private_key"; let BlueskyPublicKey = "bluesky_public_key"; let BlueskyNonce = "bluesky_nonce"; diff --git a/JS/setting.js b/JS/setting.js index ac2b7e2..6170cd3 100644 --- a/JS/setting.js +++ b/JS/setting.js @@ -26,9 +26,10 @@ let BlueskyApp = "https://bsky.app"; let BlueskyPDS = "https://bsky.social"; let BlueskyPKCEverifer = "bluesky_pkce_verifier"; let BlueskyPKCEchallenge = "bluesky_pkce_challenge"; -let BlueskyPrivateKey = "bluesky_private_key"; let BlueskyPublicKey = "bluesky_public_key"; let BlueskyNonce = "bluesky_nonce"; +let BlueskyAccessToken = "bluesky_access_token"; +let BlueskyRefreshToken = "bluesky_refresh_token"; // Tumblr let TumblrWebsite = "https://www.tumblr.com"; @@ -70,12 +71,14 @@ MastodonLogoutButton.onclick = (event) => { // Bluesky Buttons BlueskyLoginButton.onclick = (event) => { if (BlueskyWebInput != "") { - BlueskyTestingAuthorization(); + BlueskyAPI.HandleAuthorization(BlueskyPKCEverifer, BlueskyPKCEchallenge, BlueskyNonce); } } BlueskyLogoutButton.onclick = (event) => { - // Nothing at the moment + document.cookie = BlueskyPKCEverifer + "=nothing;" + ";samesite=strict;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT;"; + document.cookie = BlueskyPKCEchallenge + "=nothing;" + ";samesite=strict;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT;"; + document.cookie = BlueskyNonce + "=nothing;" + ";samesite=strict;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT;"; } // if an access token is found, login. @@ -87,30 +90,21 @@ function CheckLogin() { MastodonWebInput.remove(); MastodonLogoutButton.setAttribute("style", ""); } else { + // Auto log in MastodonAPI.GainToken(MastodonWebsite, MastodonClientID, MastodonClientSecret, MastodonAccessToken, MastodonTokenType); } + if ((document.location.href.split("state=").length == 1 && document.location.href.split("iss==").length == 1 && document.location.href.split("code=").length == 1) || || document.cookie.split("; ").find((row) => row.startsWith(BlueskyAccessToken + "="))?.split("=").length > 1) { + // Swap the buttons + BlueskyLoginButton.remove(); + BlueskyWebInput.remove(); + BlueskyLogoutButton.setAttribute("style", ""); + } else { + // Auto log in + BlueskyAPI.GainTokens(); + } // Check for a bluesky token. } // Runs on website start. // Remove traces of "login". CheckLogin(); - -// The next section is dedicated to testing. -// WARNING: I don't know what I am doing. -await BlueskyAPI.AssertionJWT(); - -async function BlueskyTestingAuthorization() { - // Declare Variables - let WellKnown = await BlueskyAPI.GetPDSWellKnown(); - let PAREndpoint = WellKnown.pushed_authorization_request_endpoint; - - let State = BlueskyAPI.GenerateToken(64); - - let PKCEverifier = await BlueskyAPI.CreatePKCECodeVerifier(); - let PKCEchallenge = await BlueskyAPI.CreatePKCECodeChallenge(PKCEverifier); - // PAR request (beginning) - let PAR = await BlueskyAPI.PARrequest(WellKnown.pushed_authorization_request_endpoint, State, PKCEchallenge); - // Now we need to authenticate. Make sure the State stays the same throughout this whole process :] - // document.location.href = "https://bsky.social/oauth/authorize?client_id=https://fedi.crowdedgames.group/oauth/client-metadata.json&request_uri=" + PAR.request_uri; -} diff --git a/oauth/client-metadata.json b/oauth/client-metadata.json index 9ca5ace..4075d9b 100644 --- a/oauth/client-metadata.json +++ b/oauth/client-metadata.json @@ -9,7 +9,7 @@ "refresh_token" ], "redirect_uris": [ - "https://fedi.crowdedgames.group/HTML/mail.html" + "https://fedi.crowdedgames.group/HTML/setting.html" ], "response_types": [ "code"