Skip to content

Commit d5cff15

Browse files
committed
Switch to session-based form login
1 parent b80ea20 commit d5cff15

File tree

5 files changed

+100
-43
lines changed

5 files changed

+100
-43
lines changed

Dockerfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ RUN dnf install -y \
1111
krb5-libs \
1212
krb5-server \
1313
krb5-workstation \
14+
php \
15+
mod_php \
1416
mod_auth_gssapi \
1517
mod_auth_kerb \
1618
mod_auth_mellon \
@@ -33,7 +35,8 @@ ADD mellon_create_metadata.sh /usr/sbin/mellon_create_metadata.sh
3335
ADD proxy.conf /etc/httpd/conf.d/proxy.conf
3436

3537
# Add form login files
36-
ADD login.html /var/www/html/login.html
38+
ADD login.php /var/www/html/login/index.php
39+
ADD logout.php /var/www/html/logout/index.php
3740

3841
# 80 = http
3942
# 443 = https

login.html

Lines changed: 0 additions & 29 deletions
This file was deleted.

login.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
$user = apache_getenv("REMOTE_USER");
3+
$error = apache_getenv("EXTERNAL_AUTH_ERROR");
4+
$csrf_cookie = $_COOKIE["csrf"] ?: "";
5+
$csrf_form = $_POST["csrf"] ?: "";
6+
$then = $_REQUEST["then"] ?: "/";
7+
if (!empty($user) && $csrf_cookie == $csrf_form) {
8+
header("HTTPDSession: httpd_user=" . urlencode($user), true);
9+
header("Location: " . $then, true, 302);
10+
exit;
11+
}
12+
?><!DOCTYPE html>
13+
<html>
14+
<head>
15+
<title>Log In</title>
16+
<style>
17+
body { margin-top: 5em; font-family: sans-serif;}
18+
form { display: inline-block; margin: 0 auto; }
19+
label { display: inline-block; width: 100px; text-align: right; }
20+
input { display: inline-block; width: 200px; }
21+
button { width: 200px; }
22+
.row { margin-top: 10px;}
23+
.error { color: red; }
24+
</style>
25+
</head>
26+
<body>
27+
<form action="" method="POST">
28+
<div class="error"><?php echo htmlspecialchars($error) ?></div>
29+
<input name="then" type="hidden" value="<?php echo htmlspecialchars($then) ?>">
30+
<input name="csrf" type="hidden" value="<?php echo htmlspecialchars($csrf_cookie) ?>">
31+
<div class="row">
32+
<label for="inputUsername">Username:</label>
33+
<input id="inputUsername" autofocus="autofocus" name="httpd_username" type="text" value="<?php echo htmlspecialchars($_POST["httpd_username"]) ?>">
34+
</div>
35+
<div class="row">
36+
<label for="inputPassword">Password:</label>
37+
<input id="inputPassword" name="httpd_password" value="" type="password">
38+
</div>
39+
<div class="row">
40+
<button type="submit" name="login" value="Log In">Log In</button>
41+
</div>
42+
</form>
43+
</body>
44+
</html>

logout.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
$then = $_REQUEST["then"] ?: "/";
4+
header("HTTPDSession: httpd_user=", true);
5+
header("Location: " . $then, true, 302);
6+
7+
?>

proxy.conf

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -177,28 +177,60 @@ RewriteRule ^.* - [F,L]
177177
LoadModule authnz_pam_module modules/mod_authnz_pam.so
178178
LoadModule intercept_form_submit_module modules/mod_intercept_form_submit.so
179179

180-
<Location /mod_intercept_form_submit/>
181-
ProxyPass https://backend.example.com/
180+
LoadModule session_crypto_module modules/mod_session_crypto.so
181+
182+
# Enable sessions
183+
Session On
184+
SessionMaxAge 300
185+
# Specify a passphrase to encrypt the session with
186+
SessionCryptoPassphrase replace-me-with-a-unique-secret
187+
# Enable cookie sessions
188+
SessionCookieName httpd_session path=/;httponly;secure;
189+
# Prevent cookies from reaching the backend
190+
SessionCookieRemove On
191+
192+
<Location /logout>
193+
# Allow the backend to adjust the session by setting headers
194+
SessionHeader HTTPDSession
195+
</Location>
196+
197+
<Location /login>
198+
# Allow the backend to adjust the session by setting headers
199+
SessionHeader HTTPDSession
182200

183201
# Defined in /etc/pam.d/httpd-pam
184202
InterceptFormPAMService httpd-pam
185-
186203
# Use the httpd_username/httpd_password fields from the login POST
187204
InterceptFormLogin httpd_username
188205
InterceptFormPassword httpd_password
189-
190206
# Automatically append the correct realm
191-
InterceptFormLoginRealms EXAMPLE.COM
192-
193-
# Show the login page for GET requests
194-
RewriteCond %{REQUEST_METHOD} GET
195-
RewriteRule ^.*$ /login.html [L]
196-
197-
# Set the request header from the envvar if it exists
198-
RequestHeader set Remote-User %{REMOTE_USER}s env=REMOTE_USER
207+
InterceptFormLoginRealms AUTH.EXAMPLE.COM
199208
</Location>
200209

201-
210+
<Location /mod_intercept_form_submit/>
211+
# Surface the session as an apache envvar
212+
SessionEnv On
213+
214+
# extract the encoded username (via a URL-based lookahead, since HTTP_SESSION is populated later in the request handling)
215+
RewriteCond %{LA-U:ENV:HTTP_SESSION} ^(.*&)?httpd_user=([^&]+)(&.*)?$
216+
# and store it an an envvar
217+
RewriteRule .* - [E=ENCODED_SESSION_USER:%2]
218+
219+
# if we don't have a session user
220+
RewriteCond %{ENV:ENCODED_SESSION_USER} ^$
221+
# capture the raw request URL path and query
222+
RewriteCond %{THE_REQUEST} ^[^\s]+\ ([^\s]+)
223+
# and redirect to the login path with a back link to our current URL
224+
# NE = don't double-encode
225+
# B = encode the backreference
226+
# R = redirect with 302 code
227+
# L = stop processing
228+
RewriteRule .* /login/?then=%1 [NE,B,R=302,L]
229+
230+
# Set the session user into a request header and proxy
231+
RequestHeader set Remote-User "expr=%{unescape:%{env:ENCODED_SESSION_USER}}" env=ENCODED_SESSION_USER
232+
ProxyPass https://backend.example.com/
233+
</Location>
202234

203235
RequestHeader unset Remote-User
204236
RequestHeader unset X-Remote-User

0 commit comments

Comments
 (0)