(bug)(auth) pass token cross-domain when a logged-in user adds a new oauth account

This commit is contained in:
Andrea Vos 2024-06-03 19:25:42 +02:00
parent ad8cad1ea7
commit 3b25710c01
4 changed files with 48 additions and 13 deletions

View File

@ -20,7 +20,7 @@
<template v-if="providerOptions.instanceRequired">
<form
v-if="formShown"
:action="providerOptions.redirectViaHome ? `${homeUrl}/api/user/social-redirect/${provider}/${$config.locale}` : `/api/connect/${provider}`"
:action="buildSocialLoginConnectLink($config.locale, provider, providerOptions)"
class="input-group input-group-sm"
>
<input
@ -42,7 +42,7 @@
</template>
<a
v-else
:href="providerOptions.redirectViaHome ? `${homeUrl}/api/user/social-redirect/${provider}/${$config.locale}` : `/api/connect/${provider}`"
:href="buildSocialLoginConnectLink($config.locale, provider, providerOptions)"
class="badge badge-lg bg-light text-dark border"
>
<Icon v="link" />
@ -60,7 +60,7 @@
</span>
<br class="d-md-none">
<a
:href="(providerOptions.redirectViaHome ? `${homeUrl}/api/user/social-redirect/${provider}/${$config.locale}` : `/api/connect/${provider}`) + (providerOptions.instanceRequired ? `?instance=${connection.name.split('@').slice(-1)[0]}` : '')"
:href="buildSocialLoginConnectLink($config.locale, provider, providerOptions, connection.name.split('@').slice(-1)[0])"
class="badge badge-lg bg-light text-dark border"
>
<Icon v="sync" />
@ -76,7 +76,9 @@
</template>
<script>
export default {
import social from '../plugins/social.ts';
export default social.extend({
props: {
provider: { required: true },
providerOptions: { required: true },
@ -85,7 +87,6 @@ export default {
data() {
return {
disconnecting: false,
homeUrl: process.env.HOME_URL,
formShown: false,
};
},
@ -108,5 +109,5 @@ export default {
await this.$alert(this.$t('user.login.brokenNotice'), 'warning');
},
},
};
});
</script>

View File

@ -69,7 +69,9 @@
</template>
<script>
export default {
import social from '../plugins/social.ts';
export default social.extend({
props: {
provider: { required: true },
options: { required: true },
@ -82,11 +84,11 @@ export default {
},
computed: {
link() {
if (this.options.redirectViaHome) {
return `${this.homeUrl}/api/user/social-redirect/${this.provider}/${this.$config.locale}`;
} else {
return `/api/connect/${this.provider}`;
}
return this.buildSocialLoginConnectLink(
this.$config.locale,
this.provider,
this.options,
);
},
},
methods: {
@ -103,5 +105,5 @@ export default {
window.location.href = this.link;
},
},
};
});
</script>

29
plugins/social.ts Normal file
View File

@ -0,0 +1,29 @@
import Vue from 'vue';
export default Vue.extend({
methods: {
buildSocialLoginConnectLink(
locale: string,
provider: string,
providerOptions: Record<string, any>,
instance: string | null = null
): string {
const url = providerOptions.redirectViaHome
? new URL(`/api/user/social-redirect/${provider}/${locale}`, process.env.HOME_URL)
: new URL(`/api/connect/${provider}`, process.env.BASE_URL);
if (providerOptions.instanceRequired && instance) {
url.searchParams.append('instance', instance ?? '');
}
if (providerOptions.redirectViaHome && this.$store.state.token) {
// if a logged in user on a domain that's not *.pronouns.page connects a new oauth account,
// home domain doesn't have the token (cross-domain cookie) and instead of connecting
// we create a brand new account. let's just pass the token to it
url.searchParams.append('token', this.$store.state.token);
}
return url.toString();
},
},
});

View File

@ -604,6 +604,9 @@ router.post('/user/:id/set-roles', handleErrorAsync(async (req, res) => {
router.get('/user/social-redirect/:provider/:locale', handleErrorAsync(async (req, res) => {
assert(req.locales.hasOwnProperty(req.params.locale));
req.session.socialRedirect = req.params.locale;
if (req.query.token) {
res.cookie('token', req.query.token, longtimeCookieSetting);
}
return res.redirect(`/api/connect/${req.params.provider}?${new URLSearchParams({
instance: req.query.instance || undefined,
})}`);