pl-fe: try to provide app id/secret when revoking oauth token

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-06-20 20:15:35 +02:00
parent ff215c5a25
commit 08098400b8
3 changed files with 35 additions and 18 deletions

View File

@ -125,7 +125,7 @@ const createUserToken = (username: string, password: string) =>
};
return obtainOAuthToken(params)
.then((token) => dispatch(authLoggedIn(token)));
.then((token) => dispatch(authLoggedIn(token, app)));
};
const otpVerify = (code: string, mfa_token: string) =>
@ -142,7 +142,7 @@ const otpVerify = (code: string, mfa_token: string) =>
challenge_type: 'totp',
// redirect_uri: 'urn:ietf:wg:oauth:2.0:oob',
// scope: getScopes(getState()),
}).then((token) => dispatch(authLoggedIn(token)));
}).then((token) => dispatch(authLoggedIn(token, app)));
};
interface VerifyCredentialsRequestAction {
@ -243,10 +243,12 @@ const logOut = () =>
if (!account) return dispatch(noOp);
const token = state.auth.users[account.url]!.access_token;
const params = {
client_id: state.auth.app?.client_id!,
client_secret: state.auth.app?.client_secret!,
token: state.auth.users[account.url]!.access_token,
client_id: state.auth.tokens[token]?.client_id || state.auth.app?.client_id!,
client_secret: state.auth.tokens[token]?.client_secret || state.auth.app?.client_secret!,
token,
};
return dispatch(revokeOAuthToken(params))
@ -294,14 +296,15 @@ const fetchOwnAccounts = () =>
};
const register = (params: CreateAccountParams) =>
(dispatch: AppDispatch) => {
async (dispatch: AppDispatch) => {
params.fullname = params.username;
return dispatch(createAppAndToken())
.then(() => dispatch(createAccount(params)))
const { app } = await dispatch(createAppAndToken());
return dispatch(createAccount(params))
.then(({ token }: { token: Token }) => {
dispatch(startOnboarding());
return dispatch(authLoggedIn(token));
return dispatch(authLoggedIn(token, app));
});
};
@ -311,11 +314,12 @@ const fetchCaptcha = () =>
interface AuthLoggedInAction {
type: typeof AUTH_LOGGED_IN;
token: Token;
app?: CredentialApplication;
}
const authLoggedIn = (token: Token) =>
const authLoggedIn = (token: Token, app?: CredentialApplication | null) =>
(dispatch: AppDispatch) => {
dispatch<AuthLoggedInAction>({ type: AUTH_LOGGED_IN, token });
dispatch<AuthLoggedInAction>({ type: AUTH_LOGGED_IN, token, app: app || undefined });
return token;
};

View File

@ -73,7 +73,8 @@ const externalLogin = (host: string) => {
const loginWithCode = (code: string) =>
(dispatch: AppDispatch) => {
const { client_id, client_secret, redirect_uri } = JSON.parse(localStorage.getItem('plfe:external:app')!);
const app = JSON.parse(localStorage.getItem('plfe:external:app')!);
const { client_id, client_secret, redirect_uri } = app;
const baseURL = localStorage.getItem('plfe:external:baseurl')!;
const scope = localStorage.getItem('plfe:external:scopes')!;
@ -87,7 +88,7 @@ const loginWithCode = (code: string) =>
};
return obtainOAuthToken(params, baseURL)
.then((token) => dispatch(authLoggedIn(token)))
.then((token) => dispatch(authLoggedIn(token, app)))
.then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL)))
.then((account) => dispatch(switchAccount(account.id)))
.then(() => window.location.href = '/');

View File

@ -44,6 +44,14 @@ const authUserSchema = v.object({
url: v.string(),
});
const tokenWithAppSchema = v.object({
...tokenSchema.entries,
client_id: v.fallback(v.optional(v.string()), undefined),
client_secret: v.fallback(v.optional(v.string()), undefined),
});
type TokenWithApp = v.InferOutput<typeof tokenWithAppSchema>;
interface AuthUser {
access_token: string;
id: string;
@ -52,7 +60,7 @@ interface AuthUser {
interface State {
app: CredentialApplication | null;
tokens: Record<string, Token>;
tokens: Record<string, TokenWithApp>;
users: Record<string, AuthUser>;
me: string | null;
client: InstanceType<typeof PlApiClient>;
@ -78,7 +86,7 @@ const getLocalState = (): State | undefined => {
return ({
app: state.app && v.parse(applicationSchema, state.app),
tokens: Object.fromEntries(Object.entries(state.tokens).map(([key, value]) => [key, v.parse(tokenSchema, value)])),
tokens: Object.fromEntries(Object.entries(state.tokens).map(([key, value]) => [key, v.parse(tokenWithAppSchema, value)])),
users: Object.fromEntries(Object.entries(state.users).map(([key, value]) => [key, v.parse(authUserSchema, value)])),
me: state.me,
client: new PlApiClient(parseBaseURL(state.me) || backendUrl, state.users[state.me]?.access_token),
@ -189,8 +197,12 @@ const initialState: State = initialize({
...localState,
});
const importToken = (state: State | Draft<State>, token: Token) => {
state.tokens[token.access_token] = token;
const importToken = (state: State | Draft<State>, token: Token, app?: CredentialApplication) => {
state.tokens[token.access_token] = {
client_id: app?.client_id,
client_secret: app?.client_secret,
...token,
};
};
// Users are now stored by their ActivityPub ID instead of their
@ -309,7 +321,7 @@ const reducer = (state: State, action: Action): State => {
});
case AUTH_LOGGED_IN:
return updateState(state, (draft) => {
importToken(draft, action.token);
importToken(draft, action.token, action.app);
});
case AUTH_LOGGED_OUT:
return updateState(state, (draft) => {