diff --git a/db_schema.sql b/db_schema.sql
index bb9e81cc2725f451f34cd3a5086a0940031e1136..096ebbb1ae2e2092928a296e613c675b30200bcd 100644
--- a/db_schema.sql
+++ b/db_schema.sql
@@ -93,6 +93,15 @@ CREATE TABLE IF NOT EXISTS `places` (
   `campus_room` varchar(20) NOT NULL,
   `campus_name` varchar(30) NOT NULL
 );
+CREATE TABLE IF NOT EXISTS `auth` (
+	`auth_id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+	`course_id` INTEGER,
+	`lecture_id` INTEGER,
+	`video_id` INTEGER,
+	`type` varchar(10),
+	`auth_user` varchar(127),
+	`auth_passwd` varchar(127)
+);
 CREATE TABLE IF NOT EXISTS `site_texts` (
   `key` varchar(64) NOT NULL PRIMARY KEY,
   `value` text NOT NULL,
diff --git a/server.py b/server.py
index 22fe44a5ad8db9b94d2b2160e05b7432240723c8..4ad08d15fb8da83d728014216bfc10b39da185fa 100755
--- a/server.py
+++ b/server.py
@@ -1,5 +1,4 @@
-#!/bin/python
-from flask import Flask, g, request, url_for, redirect, session, render_template, flash
+from flask import Flask, g, request, url_for, redirect, session, render_template, flash, Response
 from werkzeug.routing import Rule
 from functools import wraps
 from datetime import date, timedelta, datetime, time
@@ -213,21 +212,41 @@ def auth(): # For use with nginx auth_request
 		return 'Internal Server Error', 500
 	url = request.headers['X-Original-Uri'].lstrip(config['VIDEOPREFIX'])
 	ip = request.headers.get('X-Real-IP', '')
-	videos = query('''SELECT videos.path, videos.id
-			FROM videos
-			JOIN lectures ON (videos.lecture_id = lectures.id)
-			JOIN courses ON (lectures.course_id = courses.id)
-			WHERE videos.path = ?
-			AND (? OR (courses.visible AND lectures.visible AND videos.visible))''',
-			url, ismod())
-	if videos and (url.startswith('pub') or ismod()):
-		query('INSERT INTO log VALUES (?, "", ?, "video", ?, ?)', ip, datetime.now(), videos[0]['id'], url)
-		return "OK", 200
-	elif url.endswith('jpg'):
+	if url.endswith('jpg'):
 		return "OK", 200
-	else:
+	videos = query('''SELECT videos.path, videos.id, lectures.id AS lecture_id, courses.id AS course_id, protected.*
+      FROM videos
+      JOIN lectures ON (videos.lecture_id = lectures.id)
+      JOIN courses ON (lectures.course_id = courses.id)
+			LEFT JOIN protected ON (videos.id = protected.video_id OR lectures.id = protected.lecture_id OR courses.id = protected.course_id)
+      WHERE videos.path = ?
+      AND (? OR (courses.visible AND lectures.visible AND videos.visible))
+			ORDER BY protected.video_id DESC, protected.lecture_id DESC, protected.course_id DESC''',
+			url, ismod())
+	if not videos:
 		return "Not allowed", 403
-
+	first = videos[0]
+	allowed = False
+	types = []
+	auth = request.authorization
+	for video in videos:
+		if first and ((first['video_id'] and not video['video_id']) \
+			or (first['lecture_id'] and not video['lecture_id'])):
+			break
+		types.append(video['auth_type'])
+		if video['auth_type'] == 'public':
+			allowed = True
+			break
+		elif video['auth_type'] == 'password':
+			if auth and video['auth_user'] == auth.username and video['auth_passwd'] == auth.password:
+				allowed = True
+				break
+	if allowed or ismod():
+		return 'OK', 200
+		query('INSERT INTO log VALUES (?, "", ?, "video", ?, ?)', ip, datetime.now(), videos[0]['id'], url)
+	elif 'password' in types:
+		return Response("Login required", 401, {'WWW-Authenticate': 'Basic realm="Login Required"'})
+	return "Not allowed", 403
 
 @app.route('/schedule')
 @register_navbar('Drehplan', 'calendar')