From 063a29c3d09c16a0398f20ea96533c5c3fe2f459 Mon Sep 17 00:00:00 2001 From: Hailey Date: Fri, 18 Jul 2025 13:53:36 -0700 Subject: [PATCH] refactor --- .env.example | 1 + bskyweb/static/oauth-client-metadata.json | 2 +- .../static/oauth-client-metadata.native.json | 2 +- src/App.native.tsx | 10 +- src/App.web.tsx | 10 +- src/lib/hooks/useAccountSwitcher.ts | 13 +-- src/screens/Login/AuthCallback.tsx | 11 +- src/screens/Login/ChooseAccountForm.tsx | 12 +- src/screens/Login/LoginForm.tsx | 19 +++- src/state/session/agent.ts | 57 ---------- src/state/session/index.tsx | 105 +++++++----------- src/state/session/moderation.ts | 3 +- src/state/session/oauth-agent.ts | 87 +++++++++++++++ src/state/session/oauth-native-client.ts | 2 +- src/state/session/oauth-web-client.ts | 2 +- src/state/session/types.ts | 6 +- 16 files changed, 171 insertions(+), 171 deletions(-) create mode 100644 src/state/session/oauth-agent.ts diff --git a/.env.example b/.env.example index a4d21ac332..bb7b50717f 100644 --- a/.env.example +++ b/.env.example @@ -6,3 +6,4 @@ EXPO_PUBLIC_LOG_LEVEL=debug EXPO_PUBLIC_LOG_DEBUG= EXPO_PUBLIC_BUNDLE_IDENTIFIER= EXPO_PUBLIC_BUNDLE_DATE=0 +EXPO_PUBLIC_USE_OAUTH="false" diff --git a/bskyweb/static/oauth-client-metadata.json b/bskyweb/static/oauth-client-metadata.json index b7df40af81..1e036608b3 100644 --- a/bskyweb/static/oauth-client-metadata.json +++ b/bskyweb/static/oauth-client-metadata.json @@ -5,7 +5,7 @@ "redirect_uris": [ "https://bsky.hailey.at/auth/web/callback" ], - "scope": "atproto transition:generic transition:email", + "scope": "atproto transition:generic transition:email transition:chat.bsky", "token_endpoint_auth_method": "none", "response_types": [ "code" diff --git a/bskyweb/static/oauth-client-metadata.native.json b/bskyweb/static/oauth-client-metadata.native.json index 7f6f3ff50f..53c9307483 100644 --- a/bskyweb/static/oauth-client-metadata.native.json +++ b/bskyweb/static/oauth-client-metadata.native.json @@ -5,7 +5,7 @@ "redirect_uris": [ "at.hailey.bsky:/auth/native/callback" ], - "scope": "atproto transition:generic transition:email", + "scope": "atproto transition:generic transition:email transition:chat.bsky", "token_endpoint_auth_method": "none", "response_types": [ "code" diff --git a/src/App.native.tsx b/src/App.native.tsx index 56bb3dd442..87429d8458 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -93,7 +93,7 @@ beginResolveGeolocation() function InnerApp() { const [isReady, setIsReady] = React.useState(false) const {currentAccount} = useSession() - const {resumeSession, resumeSessionOauth} = useSessionApi() + const {resumeSession} = useSessionApi() const theme = useColorModeTheme() const {_} = useLingui() const hasCheckedReferrer = useStarterPackEntry() @@ -103,11 +103,7 @@ function InnerApp() { async function onLaunch(account?: SessionAccount) { try { if (account) { - if (true) { - await resumeSessionOauth(account) - } else { - await resumeSession(account) - } + await resumeSession(account) } else { await tryFetchGates(undefined, 'prefer-fresh-gates') } @@ -119,7 +115,7 @@ function InnerApp() { } const account = readLastActiveAccount() onLaunch(account) - }, [resumeSession, resumeSessionOauth]) + }, [resumeSession]) useEffect(() => { return listenSessionDropped(() => { diff --git a/src/App.web.tsx b/src/App.web.tsx index 0a8c2dd18b..04de8529ff 100644 --- a/src/App.web.tsx +++ b/src/App.web.tsx @@ -72,7 +72,7 @@ beginResolveGeolocation() function InnerApp() { const [isReady, setIsReady] = React.useState(false) const {currentAccount} = useSession() - const {resumeSession, resumeSessionOauth} = useSessionApi() + const {resumeSession} = useSessionApi() const theme = useColorModeTheme() const {_} = useLingui() const hasCheckedReferrer = useStarterPackEntry() @@ -82,11 +82,7 @@ function InnerApp() { async function onLaunch(account?: SessionAccount) { try { if (account) { - if (true) { - await resumeSessionOauth(account) - } else { - await resumeSession(account) - } + await resumeSession(account) } } catch (e) { logger.error(`session: resumeSession failed`, {message: e}) @@ -96,7 +92,7 @@ function InnerApp() { } const account = readLastActiveAccount() onLaunch(account) - }, [resumeSession, resumeSessionOauth]) + }, [resumeSession]) useEffect(() => { return listenSessionDropped(() => { diff --git a/src/lib/hooks/useAccountSwitcher.ts b/src/lib/hooks/useAccountSwitcher.ts index 3f1d34317e..7ef8266056 100644 --- a/src/lib/hooks/useAccountSwitcher.ts +++ b/src/lib/hooks/useAccountSwitcher.ts @@ -7,13 +7,14 @@ import {isWeb} from '#/platform/detection' import {type SessionAccount, useSessionApi} from '#/state/session' import {useLoggedOutViewControls} from '#/state/shell/logged-out' import * as Toast from '#/view/com/util/Toast' +import {USE_OAUTH} from '../app-info' import {logEvent} from '../statsig/statsig' import {type LogEvents} from '../statsig/statsig' export function useAccountSwitcher() { const [pendingDid, setPendingDid] = useState(null) const {_} = useLingui() - const {resumeSession, resumeSessionOauth} = useSessionApi() + const {resumeSession} = useSessionApi() const {requestSwitchToAccount} = useLoggedOutViewControls() const onPressSwitchAccount = useCallback( @@ -28,7 +29,7 @@ export function useAccountSwitcher() { try { setPendingDid(account.did) // TODO: this should be checking if it is an oauth session - if (true || account.accessJwt) { + if (USE_OAUTH || account.accessJwt) { if (isWeb) { // We're switching accounts, which remounts the entire app. // On mobile, this gets us Home, but on the web we also need reset the URL. @@ -37,11 +38,7 @@ export function useAccountSwitcher() { // So we change the URL ourselves. The navigator will pick it up on remount. history.pushState(null, '', '/') } - if (true) { - await resumeSessionOauth(account) - } else { - await resumeSession(account) - } + await resumeSession(account) logEvent('account:loggedIn', {logContext, withPassword: false}) Toast.show(_(msg`Signed in as @${account.handle}`)) } else { @@ -64,7 +61,7 @@ export function useAccountSwitcher() { setPendingDid(null) } }, - [_, resumeSession, resumeSessionOauth, requestSwitchToAccount, pendingDid], + [_, resumeSession, requestSwitchToAccount, pendingDid], ) return {onPressSwitchAccount, pendingDid} diff --git a/src/screens/Login/AuthCallback.tsx b/src/screens/Login/AuthCallback.tsx index bd9c363f02..8a5def3b3f 100644 --- a/src/screens/Login/AuthCallback.tsx +++ b/src/screens/Login/AuthCallback.tsx @@ -6,7 +6,7 @@ import {useSessionApi} from '#/state/session' import {getWebOAuthClient} from '#/state/session/oauth-web-client' export function AuthCallback() { - const {loginOauth} = useSessionApi() + const {login} = useSessionApi() const navigation = useNavigation() // TODO: handle errors, loading state, etc... @@ -18,10 +18,13 @@ export function AuthCallback() { ;(async () => { const client = getWebOAuthClient() const res = await client.callback(params) - await loginOauth(res.session, 'LoginForm') // TODO: right context? - navigation.navigate('Home') + await login( + {service: '', identifier: '', password: '', oauthSession: res.session}, + 'LoginForm', + ) + navigation.replace('Home') })() - }, [loginOauth, navigation]) + }, [login, navigation]) return null } diff --git a/src/screens/Login/ChooseAccountForm.tsx b/src/screens/Login/ChooseAccountForm.tsx index bf8473a326..fc21d96dbe 100644 --- a/src/screens/Login/ChooseAccountForm.tsx +++ b/src/screens/Login/ChooseAccountForm.tsx @@ -3,6 +3,7 @@ import {View} from 'react-native' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {USE_OAUTH} from '#/lib/app-info' import {logEvent} from '#/lib/statsig/statsig' import {logger} from '#/logger' import {type SessionAccount, useSession, useSessionApi} from '#/state/session' @@ -24,7 +25,7 @@ export const ChooseAccountForm = ({ const [pendingDid, setPendingDid] = React.useState(null) const {_} = useLingui() const {currentAccount} = useSession() - const {resumeSession, resumeSessionOauth} = useSessionApi() + const {resumeSession} = useSessionApi() const {setShowLoggedOut} = useLoggedOutViewControls() const onSelect = React.useCallback( @@ -34,7 +35,7 @@ export const ChooseAccountForm = ({ return } // TODO: this should be checking if it is an oauth session - if (!true || !account.accessJwt) { + if (!USE_OAUTH && !account.accessJwt) { // Move to login form. onSelectAccount(account) return @@ -46,11 +47,7 @@ export const ChooseAccountForm = ({ } try { setPendingDid(account.did) - if (true) { - await resumeSessionOauth(account) - } else { - await resumeSession(account) - } + await resumeSession(account) logEvent('account:loggedIn', { logContext: 'ChooseAccountForm', withPassword: false, @@ -69,7 +66,6 @@ export const ChooseAccountForm = ({ [ currentAccount, resumeSession, - resumeSessionOauth, pendingDid, onSelectAccount, setShowLoggedOut, diff --git a/src/screens/Login/LoginForm.tsx b/src/screens/Login/LoginForm.tsx index 9c6afa135d..05c717c87f 100644 --- a/src/screens/Login/LoginForm.tsx +++ b/src/screens/Login/LoginForm.tsx @@ -13,6 +13,7 @@ import { import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {USE_OAUTH} from '#/lib/app-info' import {useRequestNotificationsPermission} from '#/lib/notifications/notifications' import {isNetworkError} from '#/lib/strings/errors' import {cleanError} from '#/lib/strings/errors' @@ -53,14 +54,14 @@ interface LoginFormProps { } export function LoginForm(props: LoginFormProps) { - if (true) { - return + if (USE_OAUTH) { + return } else { return } } -function OAuthLoginForm({ +function OAuthLoginFormInner({ error, initialHandle, onPressBack, @@ -70,7 +71,7 @@ function OAuthLoginForm({ const [isProcessing, setIsProcessing] = React.useState(false) const identifierValueRef = useRef(initialHandle || '') - const {loginOauth} = useSessionApi() + const {login} = useSessionApi() const onPressNext = async () => { setIsProcessing(true) @@ -86,7 +87,15 @@ function OAuthLoginForm({ const client = getNativeOAuthClient() const res = await client.signIn(identifierValueRef.current) if (res.status === 'success') { - await loginOauth(res.session, 'LoginForm') + await login( + { + service: '', + identifier: '', + password: '', + oauthSession: res.session, + }, + 'LoginForm', + ) } else { logger.error(`Invalid OAuth status: ${res.status}`) setError(_(msg`An error occurred during authentication.`)) diff --git a/src/state/session/agent.ts b/src/state/session/agent.ts index 0e04fe5c9d..fd94141f0f 100644 --- a/src/state/session/agent.ts +++ b/src/state/session/agent.ts @@ -1,12 +1,9 @@ import { - Agent, type AtpSessionData, type AtpSessionEvent, BskyAgent, } from '@atproto/api' -import {type OutputSchema} from '@atproto/api/dist/client/types/com/atproto/server/getSession' import {TID} from '@atproto/common-web' -import {type OAuthSession} from '@atproto/oauth-client-browser' import {networkRetry} from '#/lib/async/retry' import { @@ -26,7 +23,6 @@ import { configureModerationForAccount, configureModerationForGuest, } from './moderation' -import {BSKY_OAUTH_CLIENT} from './oauth-web-client' import {type SessionAccount} from './types' import {isSessionExpired, isSignupQueued} from './util' @@ -72,22 +68,6 @@ export async function createAgentAndResume( return agent.prepare(gates, moderation, onSessionChange) } -export async function createAgentOauth(session: OAuthSession) { - const agent = new Agent(session) - const account = await oauthAgentAndSessionToSessionAccountOrThrow( - agent, - session, - ) - tryFetchGates(account.did, 'prefer-fresh-gates') - configureModerationForAccount(agent, account) - return {agent, account} -} - -export async function resumeAgentOauth(account: SessionAccount) { - const session = await BSKY_OAUTH_CLIENT.restore(account.did) - return await createAgentOauth(session) -} - export async function createAgentAndLogin( { service, @@ -207,17 +187,6 @@ export async function createAgentAndCreateAccount( return agent.prepare(gates, moderation, onSessionChange) } -export async function oauthAgentAndSessionToSessionAccountOrThrow( - agent: Agent, - session: OAuthSession, -): Promise { - const account = await oauthAgentAndSessionToSessionAccount(agent, session) - if (!account) { - throw Error('Expected an active session') - } - return account -} - export function agentToSessionAccountOrThrow(agent: BskyAgent): SessionAccount { const account = agentToSessionAccount(agent) if (!account) { @@ -226,32 +195,6 @@ export function agentToSessionAccountOrThrow(agent: BskyAgent): SessionAccount { return account } -export async function oauthAgentAndSessionToSessionAccount( - agent: Agent, - session: OAuthSession, -): Promise { - let data: OutputSchema - try { - const res = await agent.com.atproto.server.getSession() - data = res.data - } catch (e: any) { - logger.error(e) - return undefined - } - return { - service: session.serverMetadata.issuer, - did: session.did, - handle: data.handle, - email: data.email, - emailConfirmed: data.emailConfirmed, - emailAuthFactor: data.emailAuthFactor, - active: data.active, - status: data.status, - pdsUrl: session.serverMetadata.issuer, - isSelfHosted: !session.server.issuer.startsWith(BSKY_SERVICE), // TODO: is this entryway? - } -} - export function agentToSessionAccount( agent: BskyAgent, ): SessionAccount | undefined { diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx index c85faab79f..3d06898b07 100644 --- a/src/state/session/index.tsx +++ b/src/state/session/index.tsx @@ -12,8 +12,6 @@ import { createAgentAndCreateAccount, createAgentAndLogin, createAgentAndResume, - createAgentOauth, - resumeAgentOauth, sessionAccountToSession, } from './agent' import {getInitialState, reducer} from './reducer' @@ -21,11 +19,18 @@ import {getInitialState, reducer} from './reducer' export {isSignupQueued} from './util' import {addSessionDebugLog} from './logging' export type {SessionAccount} from '#/state/session/types' +import {USE_OAUTH} from '#/lib/app-info' import {logger} from '#/logger' import { + type SessionAccount, type SessionApiContext, type SessionStateContext, } from '#/state/session/types' +import { + type OauthBskyAppAgent, + oauthCreateAgent, + oauthResumeSession, +} from './oauth-agent' const StateContext = React.createContext({ accounts: [], @@ -38,11 +43,9 @@ const AgentContext = React.createContext(null) const ApiContext = React.createContext({ createAccount: async () => {}, login: async () => {}, - loginOauth: async () => {}, logoutCurrentAccount: async () => {}, logoutEveryAccount: async () => {}, resumeSession: async () => {}, - resumeSessionOauth: async () => {}, removeAccount: () => {}, }) @@ -98,15 +101,25 @@ export function Provider({children}: React.PropsWithChildren<{}>) { const login = React.useCallback( async (params, logContext) => { addSessionDebugLog({type: 'method:start', method: 'login'}) + let agentAccount: { + agent: OauthBskyAppAgent | BskyAppAgent + account: SessionAccount + } + const signal = cancelPendingTask() - const {agent, account} = await createAgentAndLogin( - params, - onAgentSessionChange, - ) + + if (params.oauthSession) { + agentAccount = await oauthCreateAgent(params.oauthSession) + } else { + agentAccount = await createAgentAndLogin(params, onAgentSessionChange) + } if (signal.aborted) { return } + + const {agent, account} = agentAccount + dispatch({ type: 'switched-to-account', newAgent: agent, @@ -122,28 +135,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) { [onAgentSessionChange, cancelPendingTask], ) - const loginOauth = React.useCallback( - async (session, logContext) => { - const signal = cancelPendingTask() - const {agent, account} = await createAgentOauth(session) - if (signal.aborted) { - return - } - dispatch({ - type: 'switched-to-account', - newAgent: agent, - newAccount: account, - }) - logger.metric( - 'account:loggedIn', - {logContext, withPassword: true}, - {statsig: true}, - ) - addSessionDebugLog({type: 'method:end', method: 'login', account}) - }, - [cancelPendingTask], - ) - const logoutCurrentAccount = React.useCallback< SessionApiContext['logoutEveryAccount'] >( @@ -190,14 +181,27 @@ export function Provider({children}: React.PropsWithChildren<{}>) { account: storedAccount, }) const signal = cancelPendingTask() - const {agent, account} = await createAgentAndResume( - storedAccount, - onAgentSessionChange, - ) + + let agentAccount: { + agent: OauthBskyAppAgent | BskyAppAgent + account: SessionAccount + } + + if (USE_OAUTH) { + agentAccount = await oauthResumeSession(storedAccount) + } else { + agentAccount = await createAgentAndResume( + storedAccount, + onAgentSessionChange, + ) + } + + const {agent, account} = agentAccount if (signal.aborted) { return } + dispatch({ type: 'switched-to-account', newAgent: agent, @@ -208,25 +212,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) { [onAgentSessionChange, cancelPendingTask], ) - const resumeSessionOauth = React.useCallback< - SessionApiContext['resumeSessionOauth'] - >( - async storedAccount => { - const signal = cancelPendingTask() - const {agent, account} = await resumeAgentOauth(storedAccount) - if (signal.aborted) { - return - } - dispatch({ - type: 'switched-to-account', - newAgent: agent, - newAccount: account, - }) - addSessionDebugLog({type: 'method:end', method: 'resumeSession', account}) - }, - [cancelPendingTask], - ) - const removeAccount = React.useCallback( account => { addSessionDebugLog({ @@ -271,13 +256,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) { a => a.did === synced.currentAccount?.did, ) // TODO: this should be checking if it is an oauth session - if (syncedAccount && (true || syncedAccount?.refreshJwt)) { + if (syncedAccount && (USE_OAUTH || syncedAccount?.refreshJwt)) { if (syncedAccount.did !== state.currentAgentState.did) { - if (true) { - resumeSessionOauth(syncedAccount) - } else { - resumeSession(syncedAccount) - } + resumeSession(syncedAccount) } else { const agent = state.currentAgentState.agent as BskyAgent const prevSession = agent.session @@ -291,7 +272,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { } } }) - }, [state, resumeSession, resumeSessionOauth]) + }, [state, resumeSession]) const stateContext = React.useMemo( () => ({ @@ -308,21 +289,17 @@ export function Provider({children}: React.PropsWithChildren<{}>) { () => ({ createAccount, login, - loginOauth, logoutCurrentAccount, logoutEveryAccount, resumeSession, - resumeSessionOauth, removeAccount, }), [ createAccount, login, - loginOauth, logoutCurrentAccount, logoutEveryAccount, resumeSession, - resumeSessionOauth, removeAccount, ], ) diff --git a/src/state/session/moderation.ts b/src/state/session/moderation.ts index f831069fdd..17d0a70249 100644 --- a/src/state/session/moderation.ts +++ b/src/state/session/moderation.ts @@ -3,7 +3,6 @@ import {type Agent, BSKY_LABELER_DID, BskyAgent} from '@atproto/api' import {IS_TEST_USER} from '#/lib/constants' import {configureAdditionalModerationAuthorities} from './additional-moderation-authorities' import {readLabelers} from './agent-config' -import {type SessionAccount} from './types' export function configureModerationForGuest() { // This global mutation is *only* OK because this code is only relevant for testing. @@ -14,7 +13,7 @@ export function configureModerationForGuest() { export async function configureModerationForAccount( agent: Agent | BskyAgent, - account: SessionAccount, + account: {did: string; handle?: string}, ) { // This global mutation is *only* OK because this code is only relevant for testing. // Don't add any other global behavior here! diff --git a/src/state/session/oauth-agent.ts b/src/state/session/oauth-agent.ts new file mode 100644 index 0000000000..f972a4f7f1 --- /dev/null +++ b/src/state/session/oauth-agent.ts @@ -0,0 +1,87 @@ +import {Agent} from '@atproto/api' +import {type OutputSchema} from '@atproto/api/dist/client/types/com/atproto/server/getSession' +import {type OAuthSession} from '@atproto/oauth-client-browser' + +import {BSKY_SERVICE} from '#/lib/constants' +import {tryFetchGates} from '#/lib/statsig/statsig' +import {logger} from '#/logger' +import {configureModerationForAccount} from './moderation' +import {BSKY_OAUTH_CLIENT} from './oauth-web-client' +import {type SessionAccount} from './types' + +export async function oauthCreateAgent(session: OAuthSession) { + const agent = new OauthBskyAppAgent(session) + const gates = tryFetchGates(session.did, 'prefer-fresh-gates') + const moderation = configureModerationForAccount(agent, session) + return agent.prepare(gates, moderation) +} + +export async function oauthResumeSession(account: SessionAccount) { + const session = await BSKY_OAUTH_CLIENT.restore(account.did) + return await oauthCreateAgent(session) +} + +export async function oauthAgentAndSessionToSessionAccountOrThrow( + agent: Agent, + session: OAuthSession, +): Promise { + const account = await oauthAgentAndSessionToSessionAccount(agent, session) + if (!account) { + throw Error('Expected an active session') + } + return account +} + +export async function oauthAgentAndSessionToSessionAccount( + agent: Agent, + session: OAuthSession, +): Promise { + let data: OutputSchema + try { + const res = await agent.com.atproto.server.getSession() + data = res.data + } catch (e: any) { + logger.error(e) + return undefined + } + return { + service: session.serverMetadata.issuer, + did: session.did, + handle: data.handle, + email: data.email, + emailConfirmed: data.emailConfirmed, + emailAuthFactor: data.emailAuthFactor, + active: data.active, + status: data.status, + pdsUrl: session.serverMetadata.issuer, + isSelfHosted: !session.server.issuer.startsWith(BSKY_SERVICE), // TODO: is this entryway? + } +} + +export class OauthBskyAppAgent extends Agent { + #session: OAuthSession + #account?: SessionAccount + + constructor(session: OAuthSession) { + super(session) + + this.#session = session + } + + async prepare(gates: Promise, moderation: Promise) { + // we have to await account fetching, since we need a separate call to getSession. this doesn't get returned in the + // OAuthSession itself, unlike the old agent + const account = await oauthAgentAndSessionToSessionAccountOrThrow( + this, + this.#session, + ) + this.#account = account + + await Promise.all([gates, moderation]) + + return {account, agent: this} + } + + // does nothing, but aligning with BskyAppAgent + dispose() {} +} diff --git a/src/state/session/oauth-native-client.ts b/src/state/session/oauth-native-client.ts index f2ac6750ec..4eef5f2a97 100644 --- a/src/state/session/oauth-native-client.ts +++ b/src/state/session/oauth-native-client.ts @@ -9,7 +9,7 @@ export function createNativeOAuthClient() { client_name: 'Bluesky Native App (Hailey Demo)', client_uri: 'https://bsky.hailey.at', redirect_uris: ['at.hailey.bsky:/auth/native/callback'], - scope: 'atproto transition:generic transition:email', + scope: 'atproto transition:generic transition:email transition:chat.bsky', token_endpoint_auth_method: 'none', response_types: ['code'], grant_types: ['authorization_code', 'refresh_token'], diff --git a/src/state/session/oauth-web-client.ts b/src/state/session/oauth-web-client.ts index 84417475b0..c719371df9 100644 --- a/src/state/session/oauth-web-client.ts +++ b/src/state/session/oauth-web-client.ts @@ -14,7 +14,7 @@ export function createWebOAuthClient() { client_name: 'Bluesky (Hailey Demo)', client_uri: 'https://bsky.hailey.at', redirect_uris: ['https://bsky.hailey.at/auth/web/callback'], - scope: 'atproto transition:generic transition:email', + scope: 'atproto transition:generic transition:email transition:chat.bsky', token_endpoint_auth_method: 'none', response_types: ['code'], grant_types: ['authorization_code', 'refresh_token'], diff --git a/src/state/session/types.ts b/src/state/session/types.ts index cd0eaf2051..8dedf18ba2 100644 --- a/src/state/session/types.ts +++ b/src/state/session/types.ts @@ -31,13 +31,10 @@ export type SessionApiContext = { identifier: string password: string authFactorToken?: string | undefined + oauthSession?: OAuthSession }, logContext: LogEvents['account:loggedIn']['logContext'], ) => Promise - loginOauth: ( - session: OAuthSession, - logContext: LogEvents['account:loggedIn']['logContext'], - ) => Promise logoutCurrentAccount: ( logContext: LogEvents['account:loggedOut']['logContext'], ) => void @@ -45,6 +42,5 @@ export type SessionApiContext = { logContext: LogEvents['account:loggedOut']['logContext'], ) => void resumeSession: (account: SessionAccount) => Promise - resumeSessionOauth: (account: SessionAccount) => Promise removeAccount: (account: SessionAccount) => void }