Skip to content

Commit

Permalink
Allow for the inferring of SP Entity IDs and ACS endpoints.
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffFranklin committed Apr 26, 2019
1 parent 0215749 commit d81b509
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 13 deletions.
50 changes: 47 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ location /saml/ {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Saml-Entity-Id https://samldemo.iamdev.s.uw.edu/saml;
# acs - post-back url registered with the IdP.
proxy_set_header X-Saml-Acs /saml/login;
proxy_pass http://saml:5000/;
}
Expand All @@ -50,3 +47,50 @@ randomly-generated string. Otherwise, we generate one on the fly, which only
works as long as the app is running, and won't work in a distributed environment.
SECRET_KEY is used to sign cookies, so setting a new key effectively
invalidates all existing sessions.


## Service Provider (SP) Entity ID and ACS URL

There are two ways to declare your SP entity-id and acs-url. With both of
these, the `X-Forwarded-` headers listed are crucial.

### By inference

With this the saml proxy will make assumptions that the request URL and proxy
path are registered as an SP.

If host https://example.com has the following proxy config...

```
location /saml/ {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /saml/;
proxy_pass http://saml:5000/;
}
```

Then the SP entity-id to register is `https://example.com/saml` and the ACS
endpoint to register is `https://example.com/saml/login`.

### Explicitly

You can also declare these items explicitly by passing them in as headers...

```
location /saml/ {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Prefix /saml/;
proxy_set_header X-Saml-Entity-Id https://samldemo.iamdev.s.uw.edu/saml;
proxy_set_header X-Saml-Acs /saml/login;
proxy_pass http://saml:5000/;
}
```

You typically won't need to explicitly declare `X-Saml-Acs`. `X-Saml-Entity-Id`
may need to be declared if for any reason the entity-id doesn't match with how
we infer it, such as with an existing entity-id, or when multiple hosts
share a single Entity ID.
19 changes: 12 additions & 7 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from flask import Flask, Response, request, session, abort, redirect
import flask
from werkzeug.contrib.fixers import ProxyFix
from werkzeug.middleware.proxy_fix import ProxyFix
import uw_saml2
from urllib.parse import urljoin
from datetime import timedelta
import os
import secrets
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_prefix=1)
POSTBACK_ROUTE = '/login'
if os.environ.get('SECRET_KEY'):
app.secret_key = os.environ['SECRET_KEY']
else:
Expand Down Expand Up @@ -56,10 +57,13 @@ def status(group=None):

def _saml_args():
"""Get entity_id and acs_url from request.headers."""
return {
'entity_id': request.headers['X-Saml-Entity-Id'],
'acs_url': urljoin(request.url_root, request.headers['X-Saml-Acs'])
}
entity_id = request.url_root[:-1] # remove trailing slash
acs_url = urljoin(request.url_root, POSTBACK_ROUTE[1:])
if 'X-Saml-Entity-Id' in request.headers:
entity_id = request.headers['X-Saml-Entity-Id']
if 'X-Saml-Acs' in request.headers:
acs_url = urljoin(request.url_root, request.headers['X-Saml-Acs'])
return dict(entity_id=entity_id, acs_url=acs_url)


@app.route('/login/')
Expand All @@ -75,6 +79,7 @@ def login_redirect(return_to=''):
return_to - the path to redirect back to after authentication. This and
the request.query_string are set on the SAML RelayState.
"""
app.logger.error(f'URL ROOT {request.url_root}')
query_string = '?' + request.query_string.decode()
if query_string == '?':
query_string = ''
Expand All @@ -85,7 +90,7 @@ def login_redirect(return_to=''):
return redirect(uw_saml2.login_redirect(return_to=return_to, **args))


@app.route('/login', methods=['GET', 'POST'])
@app.route(POSTBACK_ROUTE, methods=['GET', 'POST'])
def login():
"""
Process a SAML Response, and set the uwnetid and groups on the session.
Expand Down
5 changes: 2 additions & 3 deletions test/nginx/server.conf
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ server {

location /saml/ {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Saml-Entity-Id https://samldemo.iamdev.s.uw.edu/saml;
proxy_set_header X-Saml-Acs /saml/login;
proxy_set_header X-Forwarded-Prefix /saml/;
proxy_pass http://saml:5000/;
}

Expand Down

0 comments on commit d81b509

Please sign in to comment.