Skip to content

Commit

Permalink
Cleaner authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
rmil committed Jul 26, 2021
1 parent 1a49b36 commit 49550a0
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 58 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ This app is supposed to replace the current "watch admin" interface and make it

## Developing

Currently this will use endpoints available at [api.ystv.co.uk](https://api.ystv.co.uk), so you'll likely need to have an API token at the ready to use this endpoint.
Run `yarn install` to get all the dependencies installed. Configure the `.env` file with the parameters listed below (likely want to set `SECURITY_TYPE` to `NONE` for local dev). Then run `yarn start`.

When in "production" mode, it will use the official endpoints so an easy way to use the production token as well is modify your `/etc/hosts` and use a generic ystv sub-domain and point that at your localhost so your browser will then use the official token but you are still running creation-studio locally.
Since this is very dependant on HTTP APIs you will need to either change your hosts file (`/etc/hosts` on Linux), since CORS will become an issue if you try to use creator-studio by IP address, to a un-used subdomain with a running web-api instance available on the same domain (can be run local or remote). i.e. you could set `local.ystv.co.uk` pointing to `127.0.0.1` and have the web-api endpoint set to `api.ystv.co.uk` (remote) or `local.ystv.co.uk:8081` (local). This will allow you to use the domain's web-auth instance since cookies are shared across the entire domain.

The other option is to add a `"proxy"` key to the `package.json`, with a value of a local web-api instance and set the web-api base URL to `localhost:3000`. Which allows you to avoid CORS, but limits you to only areas which is pure web-api.

When in "production" mode (`SECURITY_TYPE = OAUTH`), it will use the official endpoints so an easy way to use the production token as well is modify your `/etc/hosts` and use a generic ystv sub-domain and point that at your localhost so your browser will then use the official token but you are still running creation-studio locally.

## .env files

You should have the following records for it to be functional:

- `REACT_APP_API_BASEURL` which would be a [web-api](https://github.com/ystv/web-api) server.
- `REACT_APP_API_BASEURL` - A [web-api](https://github.com/ystv/web-api) instance.
- `REACT_APP_SECURITY_TYPE` - Either `OAUTH` (in production) or `NONE` (local development).
- `REACT_APP_SECURITY_BASEURL` - A [web-auth](https://github.com/ystv/web-auth) instance.
- `REACT_APP_UPLOAD_ENDPOINT` - A [tusd](https://github.com/tus/tusd) instance.
- `REACT_APP_MYTV_BASEURL` - A [MyTV](https://github.com/ystv/my-tv) instance.

When developing create a `.env.local` in order to override the default. You will need to restart the development server if any changes to the environment files do occur.

Expand Down
7 changes: 4 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from "react";
import { BrowserRouter as Router } from "react-router-dom";
import Main from "./views/main";

function App() {
const App:React.FC = ():JSX.Element => {
return (
<div className="App">
<Router>
<Main />
</div>
</Router>
);
}

Expand Down
32 changes: 1 addition & 31 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React from "react";
import { Link } from "react-router-dom";
import { Layout, Menu } from "antd";
import {
Expand All @@ -11,38 +11,11 @@ import {
} from "@ant-design/icons";
import "antd/dist/antd.css";
import "../styles/main.css";
import getToken, { APIToken } from "../libraries/Auth";
import userRoles from "../types/User";

const { Sider } = Layout;
const { SubMenu } = Menu;

const Navigation: React.FC = () => {
const requiredRoles = userRoles.all;
const [token, setToken] = useState<APIToken>();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
async function getData() {
getToken()
.then((gotToken) => {
setToken(gotToken);
})
.finally(() => {
setIsLoading(false);
});
}
getData();
}, []);

if (!isLoading) {
if (token === undefined) {
return null;
}
const userHasRequiredRole = token.perms.some((role) =>
requiredRoles.includes(role.name)
);

if (process.env.REACT_APP_SECURITY_TYPE === "NONE" || userHasRequiredRole) {
return (
<Sider width={200} className="site-layout-background">
<Menu
Expand Down Expand Up @@ -111,9 +84,6 @@ const Navigation: React.FC = () => {
</Menu>
</Sider>
);
}
}
return null;
};

export default Navigation;
18 changes: 9 additions & 9 deletions src/libraries/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@ const getToken = (): Promise<APIToken> =>
}
jwt = Cookies.get("token");
}
let token;
try {
if (jwt) {
const base64Url = jwt.split(".")[1];
const base64 = base64Url.replace("-", "+").replace("_", "/");
token = JSON.parse(window.atob(base64));
let token: APIToken = JSON.parse(window.atob(base64));

if (Date.now() >= token.exp * 1000) {
return reject(new Error("expired token"));
}
return resolve(token);
}
} catch (error) {
console.log(error);
return reject(new Error("failed to get token: " + error))
}
if (token) {
return resolve(token as APIToken);
} else {
return reject(new Error("Failed to get token"));
}
});
}
);

export default getToken;

Expand Down
2 changes: 1 addition & 1 deletion src/views/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Redirect } from "react-router-dom";

const Login: React.FC = () => {
getToken().catch(() => {
return (window.location.href = `${process.env.REACT_APP_SECURITY_BASEURL}/?callback=${window.location}`);
window.location.href = `${process.env.REACT_APP_SECURITY_BASEURL}/?callback=${window.location}`
});
return <Redirect to="/" />;
};
Expand Down
22 changes: 11 additions & 11 deletions src/views/main.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from "react";
import GlobalNavigation from "../components/GlobalNavigation";
import Navbar from "../components/Navbar";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Switch, Route } from "react-router-dom";
import { Layout } from "antd";
import "antd/dist/antd.css";
import "../styles/main.css";
Expand Down Expand Up @@ -52,11 +52,14 @@ const Main: React.FC = (): JSX.Element => {
});
}, [isLoggedIn]);

return (
<>
{(isLoggedIn === undefined) ? <Loading msg={motd} /> : (isLoggedIn === true) ? (
<UserProvider user={userData}>
<Router>
switch(isLoggedIn) {
case undefined:
return <Loading msg={motd} />
case false:
return <Login />
case true:
return (
<UserProvider user={userData}>
<Layout style={{ height: "100vh" }}>
<GlobalNavigation />
<Layout>
Expand Down Expand Up @@ -95,12 +98,9 @@ const Main: React.FC = (): JSX.Element => {
</Layout>
</Layout>
</Layout>
</Router>
</UserProvider>
) : <Login />}

</>
);
)
}
};

export default Main;

0 comments on commit 49550a0

Please sign in to comment.