Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth! #11347

Merged
merged 35 commits into from
May 18, 2024
Merged

Auth! #11347

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c708953
reload the window on 401
blakeblackshear May 4, 2024
fca9281
backend apis for auth
blakeblackshear May 5, 2024
0f658c6
add login page
blakeblackshear May 5, 2024
0f6c430
re-enable web linter
blakeblackshear May 5, 2024
5acee64
fix login page routing
blakeblackshear May 5, 2024
fa34e4d
bypass csrf for internal auth endpoint
blakeblackshear May 5, 2024
7094560
disable healthcheck in devcontainer target
blakeblackshear May 5, 2024
8310063
include login page in vite build
blakeblackshear May 5, 2024
5962a24
redirect to login page on 401
blakeblackshear May 5, 2024
38f2554
implement config for users and settings
blakeblackshear May 6, 2024
bf35d16
implement JWT actual secret
blakeblackshear May 6, 2024
115d2bc
add brute force protection on login
blakeblackshear May 7, 2024
46cbe98
add support for redirecting from auth failures on api calls
blakeblackshear May 7, 2024
952df23
return location for redirect
blakeblackshear May 7, 2024
aa1d02d
default cookie name should pass regex test
blakeblackshear May 9, 2024
7cf3abc
set hash iterations to current OWASP recommendation
blakeblackshear May 9, 2024
fafc0aa
move users to database instead of config
blakeblackshear May 9, 2024
d6b517d
config option to reset admin password on startup
blakeblackshear May 12, 2024
58ae223
user management UI
blakeblackshear May 12, 2024
1284704
check for deleted user on refresh
blakeblackshear May 12, 2024
30b9c62
validate username and fixes
blakeblackshear May 12, 2024
8886ab9
remove password constraint
blakeblackshear May 12, 2024
d8904d1
cleanup
blakeblackshear May 13, 2024
034bdef
fix user check on refresh
blakeblackshear May 13, 2024
8750dfb
web fixes
blakeblackshear May 14, 2024
6d6a54c
implement auth via new external port
blakeblackshear May 15, 2024
35f02bd
use x-forwarded-for to rate limit login attempts by ip
blakeblackshear May 15, 2024
19d1aa1
implement logout and profile
blakeblackshear May 15, 2024
9b92f41
fixes
blakeblackshear May 16, 2024
46d60e4
lint fixes
blakeblackshear May 16, 2024
dd730bf
add support for user passthru from upstream proxies
blakeblackshear May 17, 2024
6cd88df
add support for specifying a logout url
blakeblackshear May 18, 2024
f27aceb
add documentation
blakeblackshear May 18, 2024
eacf790
Update docs/docs/configuration/authentication.md
blakeblackshear May 18, 2024
20b9a85
Update docs/docs/configuration/authentication.md
blakeblackshear May 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@
"features": {
"ghcr.io/devcontainers/features/common-utils:1": {}
},
"forwardPorts": [5000, 5001, 5173, 8554, 8555],
"forwardPorts": [8080, 5000, 5001, 5173, 8554, 8555],
"portsAttributes": {
"8080": {
"label": "External NGINX",
"onAutoForward": "silent"
},
"5000": {
"label": "NGINX",
"label": "Internal NGINX",
"onAutoForward": "silent"
},
"5001": {
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ jobs:
node-version: 16.x
- run: npm install
working-directory: ./web
# - name: Lint
# run: npm run lint
# working-directory: ./web
- name: Lint
run: npm run lint
working-directory: ./web

web_test:
name: Web - Test
Expand Down
2 changes: 2 additions & 0 deletions docker/main/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ RUN apt-get update \
RUN --mount=type=bind,source=./docker/main/requirements-dev.txt,target=/workspace/frigate/requirements-dev.txt \
pip3 install -r requirements-dev.txt

HEALTHCHECK NONE

CMD ["sleep", "infinity"]


Expand Down
16 changes: 16 additions & 0 deletions docker/main/build_nginx.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set -euxo pipefail
NGINX_VERSION="1.25.3"
VOD_MODULE_VERSION="1.31"
SECURE_TOKEN_MODULE_VERSION="1.5"
SET_MISC_MODULE_VERSION="v0.33"
NGX_DEVEL_KIT_VERSION="v0.3.3"

cp /etc/apt/sources.list /etc/apt/sources.list.d/sources-src.list
sed -i 's|deb http|deb-src http|g' /etc/apt/sources.list.d/sources-src.list
Expand Down Expand Up @@ -49,13 +51,27 @@ wget https://github.com/kaltura/nginx-secure-token-module/archive/refs/tags/${SE
tar -zxf ${SECURE_TOKEN_MODULE_VERSION}.tar.gz -C /tmp/nginx-secure-token-module --strip-components=1
rm ${SECURE_TOKEN_MODULE_VERSION}.tar.gz

mkdir /tmp/ngx_devel_kit
wget https://github.com/vision5/ngx_devel_kit/archive/refs/tags/${NGX_DEVEL_KIT_VERSION}.tar.gz
tar -zxf ${NGX_DEVEL_KIT_VERSION}.tar.gz -C /tmp/ngx_devel_kit --strip-components=1
rm ${NGX_DEVEL_KIT_VERSION}.tar.gz

mkdir /tmp/nginx-set-misc-module
wget https://github.com/openresty/set-misc-nginx-module/archive/refs/tags/${SET_MISC_MODULE_VERSION}.tar.gz
tar -zxf ${SET_MISC_MODULE_VERSION}.tar.gz -C /tmp/nginx-set-misc-module --strip-components=1
rm ${SET_MISC_MODULE_VERSION}.tar.gz

cd /tmp/nginx

./configure --prefix=/usr/local/nginx \
--with-file-aio \
--with-http_sub_module \
--with-http_ssl_module \
--with-http_auth_request_module \
--with-http_realip_module \
--with-threads \
--add-module=../ngx_devel_kit \
--add-module=../nginx-set-misc-module \
--add-module=../nginx-vod-module \
--add-module=../nginx-secure-token-module \
--with-cc-opt="-O3 -Wno-error=implicit-fallthrough"
Expand Down
2 changes: 2 additions & 0 deletions docker/main/requirements-wheels.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
click == 8.1.*
Flask == 3.0.*
Flask_Limiter == 3.6.*
imutils == 0.5.*
joserfc == 0.9.*
markupsafe == 2.1.*
matplotlib == 3.8.*
mypy == 1.6.1
Expand Down
43 changes: 43 additions & 0 deletions docker/main/rootfs/usr/local/nginx/conf/auth_location.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
set $upstream_auth http://127.0.0.1:5001/auth;

## Virtual endpoint created by nginx to forward auth requests.
location /auth {
## Essential Proxy Configuration
internal;
proxy_pass $upstream_auth;

## Headers

# First strip out all the request headers
# Note: This is important to ensure that upgrade requests for secure
# websockets dont cause the backend to fail
proxy_pass_request_headers off;
# Pass info about the request
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Server-Port $server_port;
proxy_set_header Content-Length "";
# Pass along auth related info
proxy_set_header Authorization $http_authorization;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-CSRF-TOKEN "1";

# include headers from common auth proxies
include proxy_trusted_headers.conf;

## Basic Proxy Configuration
proxy_pass_request_body off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 4 32k;
client_body_buffer_size 128k;

## Advanced Proxy Configuration
send_timeout 5m;
proxy_read_timeout 240;
proxy_send_timeout 240;
proxy_connect_timeout 240;
}
22 changes: 22 additions & 0 deletions docker/main/rootfs/usr/local/nginx/conf/auth_request.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Send a subrequest to verify if the user is authenticated and has permission to access the resource.
auth_request /auth;

## Save the upstream metadata response headers from Authelia to variables.
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;

## Inject the metadata response headers from the variables into the request made to the backend.
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Email $email;
proxy_set_header Remote-Name $name;

## Refresh the cookie as needed
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;

## Pass the location header back up if it exists
auth_request_set $redirection_url $upstream_http_location;
add_header Location $redirection_url;
33 changes: 31 additions & 2 deletions docker/main/rootfs/usr/local/nginx/conf/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ http {
}

server {
# intended for external traffic, protected by auth
listen [::]:8080 ipv6only=off;
# intended for internal traffic, not protected by auth
listen [::]:5000 ipv6only=off;

# vod settings
Expand Down Expand Up @@ -95,7 +98,10 @@ http {
gzip on;
gzip_types application/vnd.apple.mpegurl;

include auth_location.conf;

location /vod/ {
include auth_request.conf;
aio threads;
vod hls;

Expand All @@ -107,6 +113,7 @@ http {
}

location /stream/ {
include auth_request.conf;
add_header Cache-Control "no-store";
expires off;

Expand All @@ -121,7 +128,7 @@ http {
}

location /clips/ {

include auth_request.conf;
types {
video/mp4 mp4;
image/jpeg jpg;
Expand All @@ -137,6 +144,7 @@ http {
}

location /recordings/ {
include auth_request.conf;
types {
video/mp4 mp4;
}
Expand All @@ -147,6 +155,7 @@ http {
}

location /exports/ {
include auth_request.conf;
types {
video/mp4 mp4;
}
Expand All @@ -157,17 +166,20 @@ http {
}

location /ws {
include auth_request.conf;
proxy_pass http://mqtt_ws/;
include proxy.conf;
}

location /live/jsmpeg/ {
include auth_request.conf;
proxy_pass http://jsmpeg/;
include proxy.conf;
}

# frigate lovelace card uses this path
location /live/mse/api/ws {
include auth_request.conf;
limit_except GET {
deny all;
}
Expand All @@ -176,6 +188,7 @@ http {
}

location /live/webrtc/api/ws {
include auth_request.conf;
limit_except GET {
deny all;
}
Expand All @@ -185,6 +198,7 @@ http {

# pass through go2rtc player
location /live/webrtc/webrtc.html {
include auth_request.conf;
limit_except GET {
deny all;
}
Expand All @@ -194,6 +208,7 @@ http {

# frontend uses this to fetch the version
location /api/go2rtc/api {
include auth_request.conf;
limit_except GET {
deny all;
}
Expand All @@ -203,6 +218,7 @@ http {

# integration uses this to add webrtc candidate
location /api/go2rtc/webrtc {
include auth_request.conf;
limit_except POST {
deny all;
}
Expand All @@ -211,12 +227,14 @@ http {
}

location ~* /api/.*\.(jpg|jpeg|png|webp|gif)$ {
include auth_request.conf;
rewrite ^/api/(.*)$ $1 break;
proxy_pass http://frigate_api;
include proxy.conf;
}

location /api/ {
include auth_request.conf;
add_header Cache-Control "no-store";
expires off;
proxy_pass http://frigate_api/;
Expand All @@ -231,19 +249,29 @@ http {
add_header X-Cache-Status $upstream_cache_status;

location /api/vod/ {
include auth_request.conf;
proxy_pass http://frigate_api/vod/;
include proxy.conf;
proxy_cache off;
}

location /api/login {
auth_request off;
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://frigate_api;
include proxy.conf;
}

location /api/stats {
include auth_request.conf;
access_log off;
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://frigate_api;
include proxy.conf;
}

location /api/version {
include auth_request.conf;
access_log off;
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://frigate_api;
Expand All @@ -252,6 +280,7 @@ http {
}

location / {
# do not require auth for static assets
add_header Cache-Control "no-store";
expires off;

Expand All @@ -273,7 +302,7 @@ http {
sub_filter_once off;

root /opt/frigate/web;
try_files $uri $uri/ /index.html;
try_files $uri $uri.html $uri/ /index.html;
}
}
}
26 changes: 24 additions & 2 deletions docker/main/rootfs/usr/local/nginx/conf/proxy.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
proxy_http_version 1.1;
## Headers
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-URI $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;

## Basic Proxy Configuration
client_body_buffer_size 128k;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; ## Timeout if the real server is dead.
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 64 256k;

## Advanced Proxy Configuration
send_timeout 5m;
proxy_read_timeout 360;
proxy_send_timeout 360;
proxy_connect_timeout 360;
22 changes: 22 additions & 0 deletions docker/main/rootfs/usr/local/nginx/conf/proxy_trusted_headers.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# these headers will be copied to the /auth request and are available
# to be mapped in the config to Frigate's remote-user header

# List of headers sent by common authentication proxies:
# - Authelia
# - Traefik forward auth
# - oauth2_proxy
# - Authentik

proxy_set_header Remote-User $http_remote_user;
proxy_set_header Remote-Groups $http_remote_groups;
proxy_set_header Remote-Email $http_remote_email;
proxy_set_header Remote-Name $http_remote_name;
proxy_set_header X-Forwarded-User $http_x_forwarded_user;
proxy_set_header X-Forwarded-Groups $http_x_forwarded_groups;
proxy_set_header X-Forwarded-Email $http_x_forwarded_email;
proxy_set_header X-Forwarded-Preferred-Username $http_x_forwarded_preferred_username;
proxy_set_header X-authentik-username $http_x_authentik_username;
proxy_set_header X-authentik-groups $http_x_authentik_groups;
proxy_set_header X-authentik-email $http_x_authentik_email;
proxy_set_header X-authentik-name $http_x_authentik_name;
proxy_set_header X-authentik-uid $http_x_authentik_uid;
Loading
Loading