feat(frontend): encode Original URI in Authentication Redirect (#3026)

This commit is contained in:
John Joyce 2021-08-04 11:55:03 -07:00 committed by GitHub
parent 2fc71da58d
commit fa8f8b239a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 6 deletions

View File

@ -4,6 +4,9 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.linkedin.common.urn.CorpuserUrn;
import com.typesafe.config.Config;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.pac4j.core.client.Client;
import org.pac4j.core.context.session.SessionStore;
@ -32,6 +35,8 @@ import static react.auth.AuthUtils.*;
public class AuthenticationController extends Controller {
private static final String AUTH_REDIRECT_URI_PARAM = "redirect_uri";
private final Logger _logger = LoggerFactory.getLogger(AuthenticationController.class.getName());
private final Config _configs;
private final OidcConfigs _oidcConfigs;
@ -58,8 +63,12 @@ public class AuthenticationController extends Controller {
*/
@Nonnull
public Result authenticate() {
final Optional<String> maybeRedirectPath = Optional.ofNullable(ctx().request().getQueryString(AUTH_REDIRECT_URI_PARAM));
final String redirectPath = maybeRedirectPath.orElse("/");
if (AuthUtils.isAuthenticated(ctx())) {
return redirect("/");
return redirect(redirectPath);
}
// 1. If indirect auth is enabled, redirect to IdP
@ -72,12 +81,12 @@ public class AuthenticationController extends Controller {
// 2. If JAAS auth is enabled, fallback to it
if (_jaasConfigs.isJAASEnabled()) {
return redirect(LOGIN_ROUTE);
return redirect(LOGIN_ROUTE + String.format("?%s=%s", AUTH_REDIRECT_URI_PARAM, encodeRedirectUri(redirectPath)));
}
// 3. If no auth enabled, fallback to using default user account & redirect.
session().put(ACTOR, DEFAULT_ACTOR_URN.toString());
return redirect("/").withCookies(createActorCookie(DEFAULT_ACTOR_URN.toString(), _configs.hasPath(SESSION_TTL_CONFIG_PATH)
return redirect(redirectPath).withCookies(createActorCookie(DEFAULT_ACTOR_URN.toString(), _configs.hasPath(SESSION_TTL_CONFIG_PATH)
? _configs.getInt(SESSION_TTL_CONFIG_PATH)
: DEFAULT_SESSION_TTL_HOURS));
}
@ -124,4 +133,12 @@ public class AuthenticationController extends Controller {
.withMaxAge(Duration.of(30, ChronoUnit.DAYS))
.build());
}
private String encodeRedirectUri(final String redirectUri) {
try {
return URLEncoder.encode(redirectUri, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(String.format("Failed to encode redirect URI %s", redirectUri), e);
}
}
}

View File

@ -19,8 +19,9 @@ const ProtectedRoute = ({
}: {
isLoggedIn: boolean;
} & RouteProps) => {
const currentPath = window.location.pathname + window.location.search;
if (!isLoggedIn) {
window.location.replace(PageRoutes.AUTHENTICATE);
window.location.replace(`${PageRoutes.AUTHENTICATE}?redirect_uri=${encodeURIComponent(currentPath)}`);
return null;
}
return <Route {...props} />;

View File

@ -1,9 +1,10 @@
import React, { useCallback, useState } from 'react';
import * as QueryString from 'query-string';
import { Input, Button, Form, message, Image } from 'antd';
import { UserOutlined, LockOutlined } from '@ant-design/icons';
import { useReactiveVar } from '@apollo/client';
import { useTheme } from 'styled-components';
import { Redirect } from 'react-router';
import { Redirect, useLocation } from 'react-router';
import styles from './login.module.css';
import { Message } from '../shared/Message';
import { isLoggedInVar } from './checkAuthStatus';
@ -18,6 +19,7 @@ export type LogInProps = Record<string, never>;
export const LogIn: React.VFC<LogInProps> = () => {
const isLoggedIn = useReactiveVar(isLoggedInVar);
const location = useLocation();
const themeConfig = useTheme();
const [loading, setLoading] = useState(false);
@ -47,7 +49,9 @@ export const LogIn: React.VFC<LogInProps> = () => {
}, []);
if (isLoggedIn) {
return <Redirect to="/" />;
const params = QueryString.parse(location.search);
const maybeRedirectUri = params.redirect_uri;
return <Redirect to={(maybeRedirectUri && decodeURIComponent(maybeRedirectUri as string)) || '/'} />;
}
return (