| 54 | |
| 55 | |
| 56 | class AuthService(AuthServiceInterface, BaseService): |
| 57 | User = namedtuple('User', ['username', 'password', 'permissions']) |
| 58 | |
| 59 | def __init__(self): |
| 60 | self.user_map = dict() |
| 61 | self.log = self.add_service('auth_svc', self) |
| 62 | self._login_handler = None |
| 63 | self._default_login_handler = None |
| 64 | |
| 65 | @property |
| 66 | def default_login_handler(self): |
| 67 | return self._default_login_handler |
| 68 | |
| 69 | async def apply(self, app, users): |
| 70 | if users: |
| 71 | for group, user in users.items(): |
| 72 | self.log.debug('Created authentication group: %s', group) |
| 73 | for username, password in user.items(): |
| 74 | await self.create_user(username, password, group) |
| 75 | app.user_map = self.user_map |
| 76 | fernet_key = fernet.Fernet.generate_key() |
| 77 | secret_key = base64.urlsafe_b64decode(fernet_key) |
| 78 | storage = EncryptedCookieStorage(secret_key, cookie_name=COOKIE_SESSION) |
| 79 | setup_session(app, storage) |
| 80 | policy = SessionIdentityPolicy() |
| 81 | setup_security(app, policy, DictionaryAuthorizationPolicy(self.user_map)) |
| 82 | |
| 83 | async def create_user(self, username, password, group): |
| 84 | self.user_map[username] = self.User(username, password, (group, 'app'), ) |
| 85 | |
| 86 | @staticmethod |
| 87 | async def logout_user(request): |
| 88 | await forget(request, web.Response()) |
| 89 | raise web.HTTPFound('/') |
| 90 | |
| 91 | async def login_user(self, request): |
| 92 | """Log a user in and save the session |
| 93 | |
| 94 | :param request: |
| 95 | :raises web.HTTPRedirection: the HTTP response/location of where the user is trying to navigate |
| 96 | :raises web.HTTPUnauthorized: HTTP unauthorized response as provided by the login handler. |
| 97 | :raises web.HTTPForbidden: HTTP forbidden response as provided by the login handler. |
| 98 | :raises web.HTTPSuccessful: HTTP successful response as provided by the login handler. |
| 99 | """ |
| 100 | try: |
| 101 | self.log.debug('Using login handler "%s" for login', self._login_handler.name) |
| 102 | await self._login_handler.handle_login(request) |
| 103 | except (web.HTTPRedirection, web.HTTPUnauthorized, web.HTTPForbidden, web.HTTPSuccessful) as allowed_exception: |
| 104 | raise allowed_exception |
| 105 | except Exception as e: |
| 106 | self.log.exception('Exception when handling login request.') |
| 107 | |
| 108 | # Fallback if not already using default login handler |
| 109 | if not isinstance(self._login_handler, DefaultLoginHandler): |
| 110 | self.log.debug('Falling back to default login handler') |
| 111 | return await self._default_login_handler.handle_login(request) |
| 112 | else: |
| 113 | # We ran into an unexpected exception when using the default login handler. |
no outgoing calls