Auto-redirect single auth provider OIDC installations to login
closes #6167
This commit is contained in:
@@ -2,14 +2,12 @@ import { EmailIcon } from "outline-icons";
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Client } from "@shared/types";
|
|
||||||
import { parseDomain } from "@shared/utils/domains";
|
|
||||||
import ButtonLarge from "~/components/ButtonLarge";
|
import ButtonLarge from "~/components/ButtonLarge";
|
||||||
import InputLarge from "~/components/InputLarge";
|
import InputLarge from "~/components/InputLarge";
|
||||||
import PluginIcon from "~/components/PluginIcon";
|
import PluginIcon from "~/components/PluginIcon";
|
||||||
import env from "~/env";
|
|
||||||
import { client } from "~/utils/ApiClient";
|
import { client } from "~/utils/ApiClient";
|
||||||
import Desktop from "~/utils/Desktop";
|
import Desktop from "~/utils/Desktop";
|
||||||
|
import { getRedirectUrl } from "../getRedirectUrl";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -19,25 +17,6 @@ type Props = {
|
|||||||
onEmailSuccess: (email: string) => void;
|
onEmailSuccess: (email: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function useRedirectHref(authUrl: string) {
|
|
||||||
// If we're on a custom domain or a subdomain then the auth must point to the
|
|
||||||
// apex (env.URL) for authentication so that the state cookie can be set and read.
|
|
||||||
// We pass the host into the auth URL so that the server can redirect on error
|
|
||||||
// and keep the user on the same page.
|
|
||||||
const { custom, teamSubdomain, host } = parseDomain(window.location.origin);
|
|
||||||
const url = new URL(env.URL);
|
|
||||||
url.pathname = authUrl;
|
|
||||||
|
|
||||||
if (custom || teamSubdomain) {
|
|
||||||
url.searchParams.set("host", host);
|
|
||||||
}
|
|
||||||
if (Desktop.isElectron()) {
|
|
||||||
url.searchParams.set("client", Client.Desktop);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function AuthenticationProvider(props: Props) {
|
function AuthenticationProvider(props: Props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showEmailSignin, setShowEmailSignin] = React.useState(false);
|
const [showEmailSignin, setShowEmailSignin] = React.useState(false);
|
||||||
@@ -76,7 +55,7 @@ function AuthenticationProvider(props: Props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const href = useRedirectHref(authUrl);
|
const href = getRedirectUrl(authUrl);
|
||||||
|
|
||||||
if (id === "email") {
|
if (id === "email") {
|
||||||
if (isCreate) {
|
if (isCreate) {
|
||||||
|
|||||||
25
app/scenes/Login/getRedirectUrl.ts
Normal file
25
app/scenes/Login/getRedirectUrl.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { Client } from "@shared/types";
|
||||||
|
import { parseDomain } from "@shared/utils/domains";
|
||||||
|
import env from "~/env";
|
||||||
|
import Desktop from "~/utils/Desktop";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we're on a custom domain or a subdomain then the auth must point to the
|
||||||
|
* apex (env.URL) for authentication so that the state cookie can be set and read.
|
||||||
|
* We pass the host into the auth URL so that the server can redirect on error
|
||||||
|
* and keep the user on the same page.
|
||||||
|
*/
|
||||||
|
export function getRedirectUrl(authUrl: string) {
|
||||||
|
const { custom, teamSubdomain, host } = parseDomain(window.location.origin);
|
||||||
|
const url = new URL(env.URL);
|
||||||
|
url.pathname = authUrl;
|
||||||
|
|
||||||
|
if (custom || teamSubdomain) {
|
||||||
|
url.searchParams.set("host", host);
|
||||||
|
}
|
||||||
|
if (Desktop.isElectron()) {
|
||||||
|
url.searchParams.set("client", Client.Desktop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ import { detectLanguage } from "~/utils/language";
|
|||||||
import AuthenticationProvider from "./components/AuthenticationProvider";
|
import AuthenticationProvider from "./components/AuthenticationProvider";
|
||||||
import BackButton from "./components/BackButton";
|
import BackButton from "./components/BackButton";
|
||||||
import Notices from "./components/Notices";
|
import Notices from "./components/Notices";
|
||||||
|
import { getRedirectUrl } from "./getRedirectUrl";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children?: (config?: Config) => React.ReactNode;
|
children?: (config?: Config) => React.ReactNode;
|
||||||
@@ -227,6 +228,12 @@ function Login({ children }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there is only one provider and it's OIDC, redirect immediately.
|
||||||
|
if (config.providers.length === 1 && config.providers[0].id === "oidc") {
|
||||||
|
window.location.href = getRedirectUrl(config.providers[0].authUrl);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Background>
|
<Background>
|
||||||
<BackButton config={config} />
|
<BackButton config={config} />
|
||||||
|
|||||||
Reference in New Issue
Block a user