mirror of
https://github.com/snachodog/tok-to-insta-follower-bridge.git
synced 2025-04-17 17:22:23 -06:00
✨ support 2FA auth
This commit is contained in:
parent
f7e2c58c72
commit
9544a7f67c
@ -1,24 +1,35 @@
|
|||||||
import type { PlasmoMessaging } from "@plasmohq/messaging";
|
import type { PlasmoMessaging } from "@plasmohq/messaging";
|
||||||
import { BskyClient } from "../../lib/bskyClient";
|
import { BskyClient } from "../../lib/bskyClient";
|
||||||
|
import { AUTH_FACTOR_TOKEN_REQUIRED_ERROR_MESSAGE } from "~lib/constants";
|
||||||
|
import { ComAtprotoServerCreateSession } from "@atproto/api";
|
||||||
|
|
||||||
const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
|
const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
|
||||||
const { identifier, password } = req.body;
|
const { identifier, password, authFactorToken } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const agent = await BskyClient.createAgent({
|
const agent = await BskyClient.createAgent({
|
||||||
identifier,
|
identifier,
|
||||||
password,
|
password,
|
||||||
|
...(authFactorToken && { authFactorToken: authFactorToken }),
|
||||||
});
|
});
|
||||||
|
|
||||||
res.send({
|
res.send({
|
||||||
session: agent.session,
|
session: agent.session,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
res.send({
|
if (e instanceof ComAtprotoServerCreateSession.AuthFactorTokenRequiredError) {
|
||||||
error: {
|
res.send({
|
||||||
message: e.message,
|
error: {
|
||||||
},
|
message: AUTH_FACTOR_TOKEN_REQUIRED_ERROR_MESSAGE,
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.send({
|
||||||
|
error: {
|
||||||
|
message: e.message,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ const clientCache = new Map<string, BskyClient>();
|
|||||||
export type BskyLoginParams = {
|
export type BskyLoginParams = {
|
||||||
identifier: string;
|
identifier: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
authFactorToken?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class BskyClient {
|
export class BskyClient {
|
||||||
@ -49,11 +50,13 @@ export class BskyClient {
|
|||||||
public static async createAgent({
|
public static async createAgent({
|
||||||
identifier,
|
identifier,
|
||||||
password,
|
password,
|
||||||
|
authFactorToken,
|
||||||
}: BskyLoginParams): Promise<BskyClient> {
|
}: BskyLoginParams): Promise<BskyClient> {
|
||||||
const client = new BskyClient();
|
const client = new BskyClient();
|
||||||
const { data } = await client.agent.login({
|
const { data } = await client.agent.login({
|
||||||
identifier,
|
identifier,
|
||||||
password,
|
password,
|
||||||
|
...(authFactorToken && { authFactorToken }),
|
||||||
});
|
});
|
||||||
client.me = {
|
client.me = {
|
||||||
did: data.did,
|
did: data.did,
|
||||||
|
@ -73,3 +73,5 @@ export const MATCH_TYPE_LABEL_AND_COLOR = {
|
|||||||
color: "secondary",
|
color: "secondary",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const AUTH_FACTOR_TOKEN_REQUIRED_ERROR_MESSAGE = "AuthFactorTokenRequiredError";
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
MESSAGE_TYPE,
|
MESSAGE_TYPE,
|
||||||
STORAGE_KEYS,
|
STORAGE_KEYS,
|
||||||
TARGET_URLS_REGEX,
|
TARGET_URLS_REGEX,
|
||||||
|
AUTH_FACTOR_TOKEN_REQUIRED_ERROR_MESSAGE,
|
||||||
} from "~lib/constants";
|
} from "~lib/constants";
|
||||||
|
|
||||||
function IndexPopup() {
|
function IndexPopup() {
|
||||||
@ -18,6 +19,9 @@ function IndexPopup() {
|
|||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [identifier, setIdentifier] = useState("");
|
const [identifier, setIdentifier] = useState("");
|
||||||
const [reloadCount, setReloadCount] = useState(0);
|
const [reloadCount, setReloadCount] = useState(0);
|
||||||
|
const [authFactorToken, setAuthFactorToken] = useState("");
|
||||||
|
const [isShowAuthFactorTokenInput, setIsShowAuthFactorTokenInput] =
|
||||||
|
useState(false);
|
||||||
const [message, setMessage] = useState<null | {
|
const [message, setMessage] = useState<null | {
|
||||||
type: (typeof MESSAGE_TYPE)[keyof typeof MESSAGE_TYPE];
|
type: (typeof MESSAGE_TYPE)[keyof typeof MESSAGE_TYPE];
|
||||||
message: string;
|
message: string;
|
||||||
@ -68,7 +72,7 @@ function IndexPopup() {
|
|||||||
|
|
||||||
if (!Object.values(TARGET_URLS_REGEX).some((r) => r.test(currentUrl))) {
|
if (!Object.values(TARGET_URLS_REGEX).some((r) => r.test(currentUrl))) {
|
||||||
setErrorMessage(
|
setErrorMessage(
|
||||||
"Error: Invalid page. please open the Twitter following or blocking page.",
|
"Error: Invalid page. please open the 𝕏 following or blocking or list page.",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -101,10 +105,15 @@ function IndexPopup() {
|
|||||||
body: {
|
body: {
|
||||||
identifier: formattedIdentifier,
|
identifier: formattedIdentifier,
|
||||||
password,
|
password,
|
||||||
|
...(authFactorToken && { authFactorToken: authFactorToken.trim() }),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (res.hasError) {
|
if (res.hasError) {
|
||||||
setErrorMessage(res.message);
|
if (res.message === AUTH_FACTOR_TOKEN_REQUIRED_ERROR_MESSAGE) {
|
||||||
|
setIsShowAuthFactorTokenInput(true);
|
||||||
|
} else {
|
||||||
|
setErrorMessage(res.message);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
@ -210,6 +219,40 @@ function IndexPopup() {
|
|||||||
className="input input-bordered input-sm w-full max-w-xs join-item focus:outline-none"
|
className="input input-bordered input-sm w-full max-w-xs join-item focus:outline-none"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
{isShowAuthFactorTokenInput && (
|
||||||
|
<>
|
||||||
|
<label className="join mt-2 w-full" htmlFor="authFactorToken">
|
||||||
|
<span className="join-item btn btn-sm btn-active cursor-default">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
stroke="currentColor"
|
||||||
|
className="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M16.5 6v.75m0 3v.75m0 3v.75m0 3V18m-9-5.25h5.25M7.5 15h3M3.375 5.25c-.621 0-1.125.504-1.125 1.125v3.026a2.999 2.999 0 0 1 0 5.198v3.026c0 .621.504 1.125 1.125 1.125h17.25c.621 0 1.125-.504 1.125-1.125v-3.026a2.999 2.999 0 0 1 0-5.198V6.375c0-.621-.504-1.125-1.125-1.125H3.375Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="authFactorToken"
|
||||||
|
placeholder="2FA token"
|
||||||
|
value={authFactorToken}
|
||||||
|
onChange={(e) => setAuthFactorToken(e.target.value)}
|
||||||
|
className="input input-bordered input-sm w-full max-w-xs join-item focus:outline-none"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<p className="mt-2 text-warning">
|
||||||
|
A 2FA token has been sent to your email. Please enter the token
|
||||||
|
above.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className={
|
className={
|
||||||
|
Loading…
x
Reference in New Issue
Block a user