| @ -1,156 +0,0 @@ | |||
| import datetime | |||
| from ipaddress import ip_address, ip_network | |||
| from django.conf import settings | |||
| from django.shortcuts import redirect | |||
| from django.utils import timezone | |||
| from django.utils.deprecation import MiddlewareMixin | |||
| from ..models import BceidUser | |||
| login_delta = datetime.timedelta(hours=2) | |||
| class AnonymousUser: | |||
| """ | |||
| Anonymous user, present mainly to provide authentication checks in templates | |||
| """ | |||
| guid = None | |||
| display_name = '' | |||
| has_accepted_terms = False | |||
| @property | |||
| def is_authenticated(self): | |||
| return False | |||
| @property | |||
| def is_anonymous(self): | |||
| return True | |||
| anonymous_user = AnonymousUser() | |||
| class BceidMiddleware(MiddlewareMixin): # pylint: disable=too-few-public-methods | |||
| """ | |||
| Simple authentication middleware for operating in the BC Government | |||
| OpenShift environment, with SiteMinder integration. | |||
| For our purposes, SiteMinder is configured to add the following headers: | |||
| BCeID: | |||
| - SMGOV_USERGUID | |||
| - SMGOV_USERDISPLAYNAME | |||
| - SM_USER | |||
| BC Services Card: | |||
| - SMGOV_USERGUID | |||
| - SMGOV_GIVENNAMES | |||
| - SMGOV_SURNAME | |||
| - SM_USER | |||
| The first two are provided on pages configured to be protected by | |||
| SiteMinder, which is currently just /login. When a user goes to the login | |||
| page, if the user is logged in, SiteMinder adds those headers with their | |||
| BCeID values; if they're not logged in, it routes them through its | |||
| login/signup page and then back to the login page, with those headers in | |||
| place. For unprotected pages, those headers are stripped if present, | |||
| preventing spoofing. | |||
| The third header is populated on every request that's proxied through | |||
| SiteMinder. For logged in users, it contains their ???; for anonymous | |||
| users, it's empty. | |||
| When we detect authentication by the presence of the first two headers, we | |||
| store those values in the user's session. On all requests, we use them to | |||
| access a local proxy object for the user (available as request.user). For | |||
| users that are not logged in, an Anonymous User substitute is present. | |||
| In a local development environment, we generate a guid based on the login | |||
| name and treat that guid/login name as guid/display name. | |||
| """ | |||
| def process_request(self, request): # pylint: disable=too-many-branches | |||
| """ | |||
| Return None after populating request.user, or necessary redirects. | |||
| If the request is not coming from inside the BC Government data centre, | |||
| redirect the request through the proxy server. | |||
| If the SiteMinder headers are present, indicating the user has just | |||
| authenticated, save those headers to the session. | |||
| Get the user's GUID and display name. If they're present, and the user | |||
| has authenticated (or we're in a local development environment), add | |||
| the local proxy user to the request; if not, store the anonymous user | |||
| instance. | |||
| """ | |||
| # HTTP_SM_USER is available on both secure and unsecure pages. If it | |||
| # has a value then we know that the user is still logged into BCeID. | |||
| # This is an additional check to make sure we aren't letting users | |||
| # access the site via their session variables after logging out of bceid | |||
| # | |||
| # Note: It's still possible that a user has logged out of one BCeID and | |||
| # logged into another BCeID via www.bceid.ca without clicking the logout | |||
| # link on our app or closing the browser. This is an extreme edge case, | |||
| # and it's not pragmatic to code against it at this time. | |||
| siteminder_user = request.META.get('HTTP_SM_USER', '') | |||
| is_localdev = settings.DEPLOYMENT_TYPE in ['localdev', 'minishift'] | |||
| update_user = False | |||
| using_bc_services_card = False | |||
| guid = request.META.get('HTTP_SMGOV_USERGUID', '') | |||
| given_names = request.META.get('HTTP_SMGOV_GIVENNAMES', '') | |||
| surname = request.META.get('HTTP_SMGOV_SURNAME', '') | |||
| displayname = request.META.get('HTTP_SMGOV_USERDISPLAYNAME', '') | |||
| # HTTP_SMGOV_USERDISPLAYNAME is not included when BC Services Card authentication is used. | |||
| if not displayname and (surname or given_names): | |||
| displayname = "{0} {1}".format(given_names, surname) | |||
| using_bc_services_card = True | |||
| # HTTP_SM_USER is typically '.' when BC Services Card authentication is used. | |||
| if (not siteminder_user or siteminder_user == '.') and given_names and surname: | |||
| siteminder_user = "{0}{1}".format(given_names.split(None, 1)[0], surname) | |||
| if guid: | |||
| request.session['smgov_userguid'] = guid | |||
| else: | |||
| guid = request.session.get('smgov_userguid') | |||
| if displayname: | |||
| request.session['smgov_userdisplayname'] = displayname | |||
| else: | |||
| displayname = request.session.get('smgov_userdisplayname') | |||
| if is_localdev: | |||
| guid = request.session.get('fake_bceid_guid') | |||
| displayname = request.session.get('login_name') | |||
| if guid and (siteminder_user or is_localdev): | |||
| request.user, created = BceidUser.objects.get_or_create(user_guid=guid) | |||
| if created: | |||
| request.session['first_login'] = True | |||
| if siteminder_user: | |||
| if created or not request.user.sm_user: | |||
| request.user.sm_user = siteminder_user | |||
| update_user = True | |||
| if request.user.is_bcsc != using_bc_services_card: | |||
| request.user.is_bcsc = using_bc_services_card | |||
| update_user = True | |||
| if request.user.display_name != displayname: | |||
| request.user.display_name = displayname | |||
| update_user = True | |||
| if (request.user.last_login is None or | |||
| timezone.now() - request.user.last_login > login_delta): | |||
| request.user.last_login = timezone.now() | |||
| update_user = True | |||
| if update_user: | |||
| request.user.save() | |||
| else: | |||
| request.user = anonymous_user | |||
| return None | |||
| @ -1,155 +0,0 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <title>Government of British Columbia</title> | |||
| <meta charset="utf-8"/> | |||
| <meta http-equiv="X-UA-Compatible" content="IE=Edge"/> | |||
| <meta name="keywords" content=""/> | |||
| <meta name="description" content=""/> | |||
| <meta name="Author" content=""/> | |||
| <link rel="icon" href="https://logon7.gov.bc.ca/clp/images/favicon.ico"> | |||
| <title>CLP</title> | |||
| <!-- mobile settings --> | |||
| <meta name="viewport" | |||
| content="width=device-width, maximum-scale=1, initial-scale=1, user-scalable=0"/> | |||
| <!-- JAVASCRIPT FILES --> | |||
| <script type="text/javascript" src="https://logon7.gov.bc.ca/clp/plugins/jquery-2.1.4.min.js"></script> | |||
| <script type="text/javascript" src="https://logon7.gov.bc.ca/clp/plugins/bootstrap/js/bootstrap.min.js"></script> | |||
| <script type="text/javascript" src="https://logon7.gov.bc.ca/clp/plugins/datepicker/js/bootstrap-datepicker.min.js"></script> | |||
| <script type="text/javascript" src="https://logon7.gov.bc.ca/clp/js/common.js"></script> | |||
| <script type="text/javascript" src="https://logon7.gov.bc.ca/clp/js/brandexample.js"></script> | |||
| <script type="text/javascript" src="https://logon7.gov.bc.ca/clp/js/form-validation.js"></script> | |||
| <script type="text/javascript" src="https://logon7.gov.bc.ca/clp/js/footer.js"></script> | |||
| <!-- CORE CSS --> | |||
| <link href="https://logon7.gov.bc.ca/clp/plugins/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> | |||
| <link href="https://logon7.gov.bc.ca/clp/css/font-awesome.css" rel="stylesheet" type="text/css"/> | |||
| <link href="https://logon7.gov.bc.ca/clp/css/main.css" rel="stylesheet" type="text/css"/> | |||
| <link href="https://logon7.gov.bc.ca/clp/plugins/datepicker/css/bootstrap-datepicker3.min.css" rel="stylesheet" type="text/css"/> | |||
| </head> | |||
| <body> | |||
| <div id="wrapper" class="main"> | |||
| <header id="bcGov" class="no-gov-brand"> | |||
| <div class="container"> | |||
| <div class="seperator"></div> | |||
| <div id="login-to" class="site-title">FAKE BCeID LOGIN – FOR SOFTWARE DEVELOPMENT PURPOSES ONLY</div> | |||
| </div> | |||
| </header> | |||
| <header id="client"> | |||
| <div class="container"> | |||
| <div> | |||
| <img src="https://logon7.gov.bc.ca/clp/branding/bceid_default_logo.jpg" class="logo" alt=""/> | |||
| </div> | |||
| </div> | |||
| </header> | |||
| <form method="POST" name="login" id="login-form" class="login-bceid-form" novalidate> | |||
| <section class="container"> | |||
| <div class="row"> | |||
| <div class="col-sm-7 col-md-8"> | |||
| <div class="panel"> | |||
| <div class="panel-heading"> | |||
| Log in with | |||
| <span id="bceidLogo" class="environment-logo bceid-environment-devv2"></span> | |||
| </div> | |||
| <div class="panel-body"> | |||
| <div class="form-element form-group"> | |||
| <label class="control-label label-with-instruction" | |||
| for="username">User ID</label> | |||
| <div class="instruction">Use a Basic BCeID</div> | |||
| <input name="user" id="username" type="text" size="20" autofocus | |||
| class="form-control input-200" autocomplete="off"/> | |||
| </div> | |||
| <div class="form-element form-group"> | |||
| <label class="control-label" for="password">Password</label> | |||
| <input name="password" type="password" class="form-control input-200" | |||
| id="password" size="20" autocomplete="off"/> | |||
| </div> | |||
| <div class="bg-error hidden"> | |||
| <div class="help-block field-help-block"> | |||
| <i class="fa fa-fw fa-exclamation-circle"></i><span | |||
| class="field-help-text"></span> | |||
| </div> | |||
| </div> | |||
| <div class="login-form-action"> | |||
| <input type="submit" name="btnSubmit" class="btn btn-primary" | |||
| value="Continue"/> | |||
| </div> | |||
| <div class="forgot"> | |||
| <a href="{% url 'register' %}" class="link-forgot">Forgot your user ID or password?</a> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="panel"> | |||
| <div class="panel-body" style="padding-bottom: 15px;"> | |||
| <div> | |||
| <strong>No account?</strong> | |||
| </div> | |||
| <a href="{% url 'register' %}" | |||
| style="text-decoration: underline; font-size: 16px; font-weight: 600;">Register for a | |||
| BCeID</a> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| ◀ <a href="./" class="link-cancel">Cancel | |||
| and return to localdev</a> | |||
| </div> | |||
| <hr class="visible-xs"> | |||
| </div> | |||
| <div class="col-sm-5 col-md-4"> | |||
| </div> | |||
| </div> | |||
| </section> | |||
| </form> | |||
| </div> | |||
| <footer class="footer-stick-to-bottom"> | |||
| <div class="container" id="AccessMessage"> | |||
| <div class="row"> | |||
| <div class="col-sm-12"> | |||
| <p>Access to or unauthorized use of data on this computer system by any person other than the authorized | |||
| employee(s) or owner(s) of an account is strictly prohibited and may result in legal action against | |||
| such person.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div id="footerWrapper"> | |||
| <div class="container"> | |||
| <div class="row"> | |||
| <div class="col-sm-12"> | |||
| <ul class="inline"> | |||
| <li data-order="1"><a href="http://www.gov.bc.ca/com/disclaimer.html">Disclaimer</a></li> | |||
| <li data-order="2"><a href="http://www.gov.bc.ca/com/privacy.html">Privacy</a></li> | |||
| <li data-order="3"><a href="http://www.gov.bc.ca/com/accessibility.html">Accessibility</a></li> | |||
| <li data-order="4"><a href="http://www.gov.bc.ca/com/copyright.html">Copyright</a></li> | |||
| </ul> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </footer> | |||
| </body> | |||
| </html> | |||
| @ -1,17 +0,0 @@ | |||
| <html> | |||
| <head> | |||
| <title>Register</title> | |||
| </head> | |||
| <body> | |||
| <h1>localdev registration is not implemented</h1> | |||
| <p>Enter <strong>any user id</strong> with the password <em><strong>divorce</strong></em> to | |||
| simulate a login in your localdev envirommnent.</p> | |||
| <a href="{% url 'oidc_authentication_init' %}">Goto Login</a> | |||
| </body> | |||
| </html> | |||
| @ -1,32 +0,0 @@ | |||
| import uuid | |||
| import binascii | |||
| from encodings.utf_8 import decode | |||
| from django.conf import settings | |||
| from django.shortcuts import render, redirect | |||
| from django.views.decorators.csrf import csrf_exempt | |||
| @csrf_exempt | |||
| def bceid(request): | |||
| """ fake bceid login for developer workstation environment """ | |||
| if request.method == "POST": | |||
| login_name = request.POST.get('user', '') | |||
| password = request.POST.get('password', '') | |||
| # just in case anyone from the general public discovers the dev server | |||
| # make sure they don't accidentally login and think this is production | |||
| if password.lower() != 'divorce': | |||
| return redirect(settings.PROXY_BASE_URL + settings.FORCE_SCRIPT_NAME[:-1] + '/bceid') | |||
| # convert the login name to a guid | |||
| hex_name = decode(binascii.hexlify(str.encode(login_name)))[0] | |||
| fake_guid = hex_name.rjust(32, '0') | |||
| # save the guid in a session variable | |||
| request.session['login_name'] = login_name | |||
| request.session['fake_bceid_guid'] = fake_guid | |||
| return redirect(settings.PROXY_BASE_URL + settings.FORCE_SCRIPT_NAME[:-1] + '/login') | |||
| else: | |||
| return render(request, 'localdev/bceid.html') | |||