fix: Improve error handling for Azure-specific errors not captured in OAuth2 strategy

This commit is contained in:
Tom Moor
2021-04-18 22:41:27 -07:00
parent 04b8d7ae7b
commit 317c52df62
6 changed files with 35 additions and 27 deletions

6
app/hooks/useQuery.js Normal file
View File

@@ -0,0 +1,6 @@
// @flow
import { useLocation } from "react-router-dom";
export default function useQuery() {
return new URLSearchParams(useLocation().search);
}

View File

@@ -1,12 +1,13 @@
// @flow
import * as React from "react";
import NoticeAlert from "components/NoticeAlert";
import useQuery from "hooks/useQuery";
type Props = {
notice?: string,
};
export default function Notices() {
const query = useQuery();
const notice = query.get("notice");
const description = query.get("description");
export default function Notices({ notice }: Props) {
return (
<>
{notice === "google-hd" && (
@@ -39,12 +40,15 @@ export default function Notices({ notice }: Props) {
try again in a few minutes.
</NoticeAlert>
)}
{notice === "auth-error" && (
<NoticeAlert>
Authentication failed we were unable to sign you in at this time.
Please try again.
</NoticeAlert>
)}
{notice === "auth-error" &&
(description ? (
<NoticeAlert>{description}</NoticeAlert>
) : (
<NoticeAlert>
Authentication failed we were unable to sign you in at this time.
Please try again.
</NoticeAlert>
))}
{notice === "expired-token" && (
<NoticeAlert>
Sorry, it looks like that sign-in link is no longer valid, please try

View File

@@ -5,7 +5,6 @@ import { BackIcon, EmailIcon } from "outline-icons";
import * as React from "react";
import { Redirect, Link, type Location } from "react-router-dom";
import styled from "styled-components";
import getQueryVariable from "shared/utils/getQueryVariable";
import ButtonLarge from "components/ButtonLarge";
import Fade from "components/Fade";
import Flex from "components/Flex";
@@ -114,7 +113,7 @@ function Login({ location }: Props) {
<Heading centered>Login to {config.name || "Outline"}</Heading>
)}
<Notices notice={getQueryVariable("notice")} />
<Notices />
{defaultProvider && (
<React.Fragment key={defaultProvider.id}>

View File

@@ -5,7 +5,6 @@ import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import styled from "styled-components";
import getQueryVariable from "shared/utils/getQueryVariable";
import Button from "components/Button";
import CollectionIcon from "components/CollectionIcon";
import Heading from "components/Heading";
@@ -18,13 +17,15 @@ import SlackIcon from "components/SlackIcon";
import SlackButton from "./components/SlackButton";
import env from "env";
import useCurrentTeam from "hooks/useCurrentTeam";
import useQuery from "hooks/useQuery";
import useStores from "hooks/useStores";
function Slack() {
const team = useCurrentTeam();
const { collections, integrations } = useStores();
const { t } = useTranslation();
const error = getQueryVariable("error");
const query = useQuery();
const error = query.get("error");
React.useEffect(() => {
collections.fetchPage({ limit: 100 });

View File

@@ -24,6 +24,17 @@ export default function createMiddleware(providerName: string) {
return ctx.redirect(`/?notice=auth-error`);
}
// Handle errors from Azure which come in the format: message, Trace ID,
// Correlation ID, Timestamp in these two query string parameters.
const { error, error_description } = ctx.request.query;
if (error && error_description) {
console.error(error_description);
// Display only the descriptive message to the user, log the rest
const description = error_description.split("Trace ID")[0];
return ctx.redirect(`/?notice=auth-error&description=${description}`);
}
if (result.user.isSuspended) {
return ctx.redirect("/?notice=suspended");
}

View File

@@ -1,13 +0,0 @@
// @flow
export default function getQueryVariable(variable: string) {
const query = window.location.search.substring(1);
const vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
const pair = vars[i].split("=");
if (pair[0] === variable) {
return pair[1];
}
}
}