Fixed redirecting back to account home after sign in in Portal (#16487)

refs https://github.com/TryGhost/Team/issues/2674

When going to /#/portal/account when not signed in, you are redirected
to the login page. But once signed in, you aren't redirected back to the
account page. This fixes this issue by adding an extra and optional
redirect parameter when requesting a magic token via email.

This new parameter allows to override the default behaviour of using the
Referer HTTP header, which doesn't include the hash/fragment part of the
URL.

The referrer is already restricted to only allow redirects to the site,
not external URLs.
This commit is contained in:
Simon Backx 2023-04-04 18:07:37 +02:00 committed by GitHub
parent 3885cab977
commit d0042b550a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 22 additions and 8 deletions

View File

@ -267,7 +267,7 @@ const createSessionFromMagicLink = async function (req, res, next) {
const redirectUrl = new URL(referrer);
redirectUrl.searchParams.set('success', true);
redirectUrl.searchParams.set('action', 'signin');
return res.redirect(redirectUrl.pathname + redirectUrl.search);
return res.redirect(redirectUrl.href);
}
}

View File

@ -146,7 +146,7 @@ describe('Members Service Middleware', function () {
it('redirects member to referrer param path on signup if it is on the site', async function () {
req.url = '/members?token=test&action=signin&r=https%3A%2F%2Fsite.com%2Fblah%2Fmy-post%2F';
req.query = {token: 'test', action: 'signin', r: 'https://site.com/blah/my-post/'};
req.query = {token: 'test', action: 'signin', r: 'https://site.com/blah/my-post/#comment-123'};
// Fake token handling failure
membersService.ssr.exchangeTokenForSession.resolves({});
@ -157,7 +157,7 @@ describe('Members Service Middleware', function () {
// Check behavior
next.calledOnce.should.be.false();
res.redirect.calledOnce.should.be.true();
res.redirect.firstCall.args[0].should.eql('/blah/my-post/?success=true&action=signin');
res.redirect.firstCall.args[0].should.eql('https://site.com/blah/my-post/?success=true&action=signin#comment-123');
});
it('does not redirect to referrer param if it is external', async function () {

View File

@ -319,12 +319,21 @@ module.exports = class RouterController {
async sendMagicLink(req, res) {
const {email, autoRedirect} = req.body;
let {emailType} = req.body;
let {emailType, redirect} = req.body;
let referer = req.get('referer');
if (autoRedirect === false){
referer = null;
}
if (redirect) {
try {
// Validate URL
referer = new URL(redirect).href;
} catch (e) {
logging.warn(e);
}
}
if (!email) {
throw new errors.BadRequestError({
message: tpl(messages.emailRequired)

View File

@ -12,7 +12,10 @@ export default class AccountHomePage extends React.Component {
const {member} = this.context;
if (!member) {
this.context.onAction('switchPage', {
page: 'signin'
page: 'signin',
pageData: {
redirect: window.location.href // This includes the search/fragment of the URL (#/portal/account) which is missing from the default referer header
}
});
}
}

View File

@ -33,9 +33,10 @@ export default class SigninPage extends React.Component {
};
}, async () => {
const {email, errors} = this.state;
const {redirect} = this.context.pageData ?? {};
const hasFormErrors = (errors && Object.values(errors).filter(d => !!d).length > 0);
if (!hasFormErrors) {
this.context.onAction('signin', {email});
this.context.onAction('signin', {email, redirect});
}
});
}

View File

@ -213,7 +213,7 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}) {
});
},
async sendMagicLink({email, emailType, labels, name, oldEmail, newsletters}) {
async sendMagicLink({email, emailType, labels, name, oldEmail, newsletters, redirect}) {
const url = endpointFor({type: 'members', resource: 'send-magic-link'});
const body = {
name,
@ -222,7 +222,8 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}) {
oldEmail,
emailType,
labels,
requestSrc: 'portal'
requestSrc: 'portal',
redirect
};
const urlHistory = getUrlHistory();
if (urlHistory) {