Skip to content
This repository has been archived by the owner on Dec 16, 2024. It is now read-only.

Commit

Permalink
fix: extension auth
Browse files Browse the repository at this point in the history
  • Loading branch information
TroyKomodo committed Oct 26, 2024
1 parent 12f543b commit 9bdb1f5
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 49 deletions.
4 changes: 2 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ import ModalViewport from "@/components/modal/ModalViewport.vue";
import ContextMenu from "@/components/overlay/ContextMenu.vue";
import { log } from "./Logger";
import Icon from "./components/utility/Icon.vue";
import { WindowSelfMessage } from "./views/window.messages";
import { WindowMessage } from "./views/window.messages";
import { setupActor } from "@/ActorLogic";
const store = useStore();
Expand Down Expand Up @@ -110,7 +110,7 @@ provideApolloClient(apolloClient);
// Set up the actor user
window.addEventListener("message", (e) => {
if (e.origin === location.origin) {
const data = e.data as WindowSelfMessage;
const data = e.data as WindowMessage;
log.info("Received message from popup", `${JSON.stringify(data)}`);
Expand Down
10 changes: 8 additions & 2 deletions src/components/utility/LoginButton.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<button
v-if="actor.user === null"
v-if="actor.user === null || redirect"
class="twitch-button"
:platform="platform"
@click="() => oauth2Authorize()"
Expand Down Expand Up @@ -32,11 +32,17 @@ const actor = useActor();
const { t } = useI18n();
const auth = useAuth();
const props = defineProps<{ redirect?: boolean }>();
const platform = ref<User.UserConnectionPlatform>("TWITCH");
/** Request the user to authorize with a third party platform */
const oauth2Authorize = () => {
auth.prompt(platform.value, false);
if (props.redirect) {
auth.redirect(platform.value, false);
} else {
auth.prompt(platform.value, false);
}
};
const { open } = useContextMenu();
Expand Down
12 changes: 12 additions & 0 deletions src/composables/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,25 @@ export function useAuth() {
);
}

function redirect(provider: User.Connection.Platform, isLink: boolean) {
const store = useStore();

const route =
`auth?platform=${provider.toLowerCase()}` +
(store.authToken ? `&token=${store.authToken}` : "") +
(isLink ? "&link_connection=true" : "");

window.location.assign(`${import.meta.env.VITE_APP_API_REST}/${route}`);
}

function logout(): Promise<void> {
const store = useStore();
return popup("auth/logout" + (store.authToken ? `?token=${store.authToken}` : ""));
}

return {
prompt,
redirect,
logout,
};
}
8 changes: 8 additions & 0 deletions src/store/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,13 @@ export const useStore = defineStore("main", {
},
});

setInterval(() => {
const token = localStorage.getItem(LocalStorageKeys.AUTH_TOKEN);
const store = useStore();
if (token !== store.authToken) {
store.setAuthToken(token);
}
}, 1000);

export type Theme = "light" | "dark";
export type NotFoundMode = "troll-despair" | "pot-friend";
37 changes: 18 additions & 19 deletions src/views/ExtensionAuth.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
<template>
<div class="extension-auth-content">
<LoginButton v-if="!actor.user" />
<LoginButton redirect />
</div>
</template>

<script setup lang="ts">
import { watch } from "vue";
import { useActor } from "@/store/actor";
import { useStore } from "@/store/main";
import LoginButton from "@/components/utility/LoginButton.vue";
import { useRouter } from "vue-router";
import LoginButton from "../components/utility/LoginButton.vue";
import { useStore } from "../store/main";
const router = useRouter();
const store = useStore();
const actor = useActor();
window.addEventListener("message", function listener(e) {
if (e.origin !== "https://www.twitch.tv") return;
if (e.data !== "7tv-token-request") return;
const opener = window.opener as Window;
window.removeEventListener("message", listener);
watch(
() => store.authToken,
(t) => {
if (!t) return;
e.source?.postMessage({ type: "7tv-token", token: t }, { targetOrigin: "https://www.twitch.tv/*" });
},
{ immediate: true },
);
});
function main() {
if (!opener) {
router.push("/");
} else if (store.authToken) {
opener.postMessage({ type: "7tv-token", token: store.authToken }, "https://www.twitch.tv");
window.close();
} else {
window.sessionStorage.setItem("7tv-extension-auth", "true");
}
}
main();
</script>

<style lang="scss">
Expand Down
64 changes: 41 additions & 23 deletions src/views/OAuth2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<script setup lang="ts">
import { useRoute, useRouter } from "vue-router";
import { useHead } from "@vueuse/head";
import { publishSelfMessage } from "./window.messages";
import { publishMessage } from "./window.messages";
import { useStore } from "../store/main";
useHead({
title: "7TV | Authentication (OAuth2 Callback)",
Expand All @@ -16,42 +17,59 @@ useHead({
const route = useRoute();
const router = useRouter();
const opener = window.opener as Window;
function handleRoute() {
if (!window.opener) {
if (!opener) {
router.replace("/");
return;
}
// Parse the token as a URLSearchParams
const params = new URLSearchParams(route.hash.slice(1));
const token = params.get("token");
const wasLinked = params.get("linked") === "true";
const isLogout = params.get("logout") === "true";
if (isLogout) {
publishSelfMessage({ event: "LOGOUT_SUCCESS" });
window.close();
return;
let is7TV;
try {
is7TV = opener.location.origin === window.origin;
} catch (e) {
is7TV = false;
}
if (wasLinked) {
publishSelfMessage({ event: "LOGIN_LINKED" });
window.close();
return;
}
if (is7TV) {
const wasLinked = params.get("linked") === "true";
const isLogout = params.get("logout") === "true";
if (!token) {
publishSelfMessage({ event: "LOGIN_FAILED" });
window.close();
return;
// Parse the token as a URLSearchParams
if (isLogout) {
publishMessage({ event: "LOGOUT_SUCCESS" });
window.close();
return;
}
if (wasLinked) {
publishMessage({ event: "LOGIN_LINKED" });
window.close();
return;
}
if (!token) {
publishMessage({ event: "LOGIN_FAILED" });
window.close();
return;
}
// Send the token back to the parent window
publishMessage({
event: "LOGIN_TOKEN",
token,
});
} else if (token && window.sessionStorage.getItem("7tv-extension-auth") === "true") {
const store = useStore();
store.setAuthToken(token);
opener.postMessage({ type: "7tv-token", token }, "https://www.twitch.tv");
}
// Send the token back to the parent window
publishSelfMessage({
event: "LOGIN_TOKEN",
token,
});
window.close();
}
Expand Down
6 changes: 3 additions & 3 deletions src/views/window.messages.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export type WindowSelfMessage =
export type WindowMessage =
| { event: "LOGIN_TOKEN"; token: string }
| { event: "LOGIN_FAILED" }
| { event: "LOGIN_LINKED" }
| { event: "LOGOUT_SUCCESS" };

export function publishSelfMessage(event: WindowSelfMessage) {
export function publishMessage(event: WindowMessage, origin = window.origin) {
if (!window.opener) throw new Error("No window.opener");

window.opener.postMessage(event, window.origin);
window.opener.postMessage(event, origin);
}

0 comments on commit 9bdb1f5

Please sign in to comment.