Skip to content

Commit

Permalink
Merge pull request #26 from briefercloud/allow-http
Browse files Browse the repository at this point in the history
feat: Introduce ALLOW_HTTP env var that allows authentication to work without https
  • Loading branch information
vieiralucas authored Sep 12, 2024
2 parents b56c79b + fbcba40 commit 6593ff4
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 70 deletions.
7 changes: 1 addition & 6 deletions apps/api/src/auth/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ import { obscureEmail } from '../emails.js'
import { comparePassword, hashPassword, isValidPassword } from '../password.js'
import properties from '../properties.js'
import { IOServer } from '../websocket/index.js'
import {
callbackUrlSchema,
cookieOptions,
sessionExpiryCookieOption,
} from './index.js'
import { callbackUrlSchema, cookieOptions } from './index.js'
import {
authenticationMiddleware,
createAuthToken,
Expand Down Expand Up @@ -51,7 +47,6 @@ export default function getRouter<H extends ApiUser>(
await confirmUser(data.userId)

res.cookie('token', createAuthToken(data.userId), cookieOptions)
res.cookie('sessionExpiry', Date.now(), sessionExpiryCookieOption)
res.redirect(data.callback)
})

Expand Down
8 changes: 1 addition & 7 deletions apps/api/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,11 @@ export const callbackUrlSchema = z

export const cookieOptions: CookieOptions = {
httpOnly: true,
secure: config().NODE_ENV === 'production',
secure: config().NODE_ENV === 'production' && !config().ALLOW_HTTP,
sameSite: 'strict',
maxAge: JWT_EXPIRATION_MS,
}

export const sessionExpiryCookieOption: CookieOptions = {
sameSite: 'strict',
maxAge: JWT_EXPIRATION_MS,
domain: config().TLD,
}

export default function authRouter(socketServer: IOServer) {
const cfg = config()

Expand Down
44 changes: 24 additions & 20 deletions apps/api/src/config/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { logger } from '../logger.js'

export interface IBaseConfig {
NODE_ENV: string
ALLOW_HTTP: boolean
VERSION: string
LOG_LEVEL: string
API_URL: string
FRONTEND_URL: string
TLD: string
LOGIN_LINK_EXPIRATION: string
LOGIN_JWT_SECRET: string
AUTH_JWT_EXPIRATION: string
Expand All @@ -35,11 +35,11 @@ export interface IBaseConfig {

export class BaseConfig implements IBaseConfig {
public readonly NODE_ENV: string
public readonly ALLOW_HTTP: boolean
public readonly VERSION: string
public readonly LOG_LEVEL: string
public readonly API_URL: string
public readonly FRONTEND_URL: string
public readonly TLD: string
public readonly LOGIN_LINK_EXPIRATION: string
public readonly LOGIN_JWT_SECRET: string
public readonly AUTH_JWT_EXPIRATION: string
Expand All @@ -65,9 +65,9 @@ export class BaseConfig implements IBaseConfig {

public constructor() {
this.NODE_ENV = getVar('NODE_ENV')
this.ALLOW_HTTP = this.getBooleanVar('ALLOW_HTTP')
this.VERSION = this.getVersion()
this.LOG_LEVEL = getVar('LOG_LEVEL')
this.TLD = getVar('TLD')
this.API_URL = getVar('API_URL')
this.FRONTEND_URL = getVar('FRONTEND_URL')
this.LOGIN_LINK_EXPIRATION = process.env['LOGIN_LINK_EXPIRATION'] || '15m'
Expand Down Expand Up @@ -104,23 +104,14 @@ export class BaseConfig implements IBaseConfig {
// can't be 0 because LRUCache doesn't allow that
1 / 1024 / 1024
)
this.ENABLE_CUSTOM_OAI_KEY = Boolean(process.env['ENABLE_CUSTOM_OAI_KEY'])

const disableTelemetry = (
process.env['DISABLE_ANONYMOUS_TELEMETRY'] ?? ''
).toLowerCase()
this.DISABLE_ANONYMOUS_TELEMETRY =
disableTelemetry === 'true' ||
disableTelemetry === '1' ||
disableTelemetry === 'yes'

const disableUpdateCheck = (
process.env['DISABLE_UPDATE_CHECK'] ?? ''
).toLowerCase()
this.DISABLE_UPDATE_CHECK =
disableUpdateCheck === 'true' ||
disableUpdateCheck === '1' ||
disableUpdateCheck === 'yes'
this.ENABLE_CUSTOM_OAI_KEY = this.getBooleanVar(
'ENABLE_CUSTOM_OAI_KEY',
true
)
this.DISABLE_ANONYMOUS_TELEMETRY = this.getBooleanVar(
'DISABLE_ANONYMOUS_TELEMETRY'
)
this.DISABLE_UPDATE_CHECK = this.getBooleanVar('DISABLE_UPDATE_CHECK')
}

private getVersion() {
Expand All @@ -145,4 +136,17 @@ export class BaseConfig implements IBaseConfig {
return 'unknown'
}
}

private getBooleanVar(name: string, or?: boolean): boolean {
const value = process.env[name]?.toLowerCase()
if (value === undefined && or !== undefined) {
return or
}

if (value === 'true' || value === '1' || value === 'yes') {
return true
}

return false
}
}
28 changes: 1 addition & 27 deletions apps/web/src/hooks/useSessionRedirect.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useWorkspaces } from '@/hooks/useWorkspaces'
import { useEffect, useCallback } from 'react'
import { useEffect } from 'react'
import { NextRouter, useRouter } from 'next/router'
import { useSession, useSignout } from '@/hooks/useAuth'
import Cookies from 'js-cookie'
import useProperties from './useProperties'

const redirectToLogin = (router: NextRouter) => {
Expand All @@ -15,31 +14,6 @@ const redirectToLogin = (router: NextRouter) => {
router.replace(path)
}

export const useCookieCheck = () => {
const session = useSession()
const router = useRouter()
const redirectOnCookieExpiry = useCallback(() => {
if (!session.data) {
return
}

const tokenExists = Cookies.get('sessionExpiry')
const isAlreadyOnLoginPage = router.asPath.includes('/auth/signin')
if (!tokenExists && !isAlreadyOnLoginPage) {
redirectToLogin(router)
}
}, [router, session])

useEffect(() => {
window.addEventListener('focus', redirectOnCookieExpiry)
const timer = setInterval(redirectOnCookieExpiry, 5000)
return () => {
window.removeEventListener('focus', redirectOnCookieExpiry)
clearInterval(timer)
}
}, [redirectOnCookieExpiry])
}

export const useSessionRedirect = (shouldRedirect = true) => {
const properties = useProperties()
const router = useRouter()
Expand Down
3 changes: 0 additions & 3 deletions apps/web/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import posthog from 'posthog-js'

import { DocumentsProvider } from '@/hooks/useDocuments'
import { EnvironmentStatusProvider } from '@/hooks/useEnvironmentStatus'
import { useCookieCheck } from '@/hooks/useSessionRedirect'
import { WebsocketProvider } from '@/hooks/useWebsocket'
import '@/styles/globals.css'
import 'simplebar-react/dist/simplebar.min.css'
Expand Down Expand Up @@ -37,8 +36,6 @@ function App({ Component, pageProps: { session, ...pageProps } }: Props) {
properties.data?.disabledAnonymousTelemetry ?? true
)

useCookieCheck()

return (
<PostHogProvider client={posthog}>
{telemetryEnabled && <Telemetry />}
Expand Down
17 changes: 10 additions & 7 deletions docs/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,27 @@ Here's a step-by-step guide to deploy Briefer as a single container:
sudo systemctl start docker
```
3. Pull and run the all-in-one Docker image for Briefer.

```bash
# if using an IP set API_URL and FRONTEND_URL to your-ip:8080
# if using an IP set API_URL to https://your-ip:3000 and FRONTEND_URL to https://your-ip:8080
docker run -d \
-p 3000:3000 \
-p 8080:8080 \
-v briefer_psql_data:/var/lib/postgresql/data \
-v briefer_jupyter_data:/home/jupyteruser \
-v briefer_briefer_data:/home/briefer \
--env API_URL="your_api_address" \
--env FRONTEND_URL="your_frontend_address" \
--env API_URL="https://your_api_address" \
--env FRONTEND_URL="https://your_frontend_address" \
briefercloud/briefer
```
ℹ️ The most crucial part of this step is to make sure that `API_URL` and `FRONTEND_URL` point to the host's address. For example, if you're running Briefer on a machine whose IP is `192.168.0.1`, you should set the `API_URL` to `192.168.0.1:8080` (considering API is running on port 8080) and `FRONTEND_URL` to `192.168.0.1:3000` (considering the front-end is running on port 3000).


ℹ️ The most crucial part of this step is to make sure that `API_URL` and `FRONTEND_URL` point to the host's address. For example, if you're running Briefer on a machine whose IP is `192.168.0.1`, you should set the `API_URL` to `https://192.168.0.1:8080` (considering API is running on port 8080) and `FRONTEND_URL` to `https://192.168.0.1:3000` (considering the front-end is running on port 3000).

ℹ️ If you want to serve Briefer over HTTP (usually because you're using an IP directly) you should consider setting `--env ALLOW_HTTP="true"` in the above command.
5. Expose your server to the internet or your local network.

4. Expose your server to the internet or your local network.
Make sure that you allow traffic on ports 3000 and 8080. The first one is for the Briefer web application (the one you'll access in your browser), and the second one is for the API that the web application talks to.
6. Create the necessary DNS records to access ports 3000 and 8080.
5. If you want to use a domain name rather than an IP, create the necessary DNS records to access ports 3000 and 8080. Otherwise, skip this step.
Use `app.briefer.your_domain_here.com` as the name for the web application bound to port 3000, and `api.briefer.your_domain_here.com` as the name for the API bound to port 8080.

Now you should be able to access the Briefer web application at `app.briefer.your_domain_here.com` and the API at `api.briefer.your_domain_here.com`.
Expand Down
1 change: 1 addition & 0 deletions pypi/src/briefer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"LOG_LEVEL",
"API_URL",
"FRONTEND_URL",
"ALLOW_HTTP",
"TLD",
"LOGIN_JWT_SECRET",
"AUTH_JWT_SECRET",
Expand Down

0 comments on commit 6593ff4

Please sign in to comment.