async def _driveToken(self, request: Request): data = await request.post() if data.get('redirect_uri') not in [ "http://localhost:{}/drive/authorize".format(self._port), 'urn:ietf:wg:oauth:2.0:oob' ]: raise HTTPUnauthorized() if data.get('grant_type') != 'authorization_code': raise HTTPUnauthorized() if not self._checkClientIdandSecret(data.get('client_id'), data.get('client_secret')): raise HTTPUnauthorized() if data.get('code') != self._drive_auth_code: raise HTTPUnauthorized() self.generateNewRefreshToken() return json_response({ 'access_token': self._auth_token, 'refresh_token': self._refresh_token, 'client_id': data.get('client_id'), 'client_secret': self.config.get(Setting.DEFAULT_DRIVE_CLIENT_SECRET), 'token_expiry': self.timeToRfc3339String(self._time.now()), })
async def _oAuth2Authorize(self, request: Request): query = request.query if query.get('client_id') != self.config.get( Setting.DEFAULT_DRIVE_CLIENT_ID) and query.get( 'client_id') != self._custom_drive_client_id: raise HTTPUnauthorized() if query.get('scope') != 'https://www.googleapis.com/auth/drive.file': raise HTTPUnauthorized() if query.get('response_type') != 'code': raise HTTPUnauthorized() if query.get('include_granted_scopes') != 'true': raise HTTPUnauthorized() if query.get('access_type') != 'offline': raise HTTPUnauthorized() if 'state' not in query: raise HTTPUnauthorized() if 'redirect_uri' not in query: raise HTTPUnauthorized() if query.get('prompt') != 'consent': raise HTTPUnauthorized() if query.get('redirect_uri') == 'urn:ietf:wg:oauth:2.0:oob': return json_response({"code": self._drive_auth_code}) url = URL(query.get('redirect_uri')).with_query({ 'code': self._drive_auth_code, 'state': query.get('state') }) raise HTTPSeeOther(str(url))
async def check_api_permissions(request, permissions): try: if await api_auth(request, list(permissions)): return True else: return False except HTTPUnauthorized: reason = "No user with this api key/session found" raise HTTPUnauthorized( reason=reason, body=dumps({ "Ok": False, "Error": reason, "status_code": 401 }), content_type="application/json", ) except HTTPForbidden: reason = f"Insufficient permissions. Permissions required: {list(permissions)}" raise HTTPForbidden( reason=reason, body=dumps({ "Ok": False, "Error": reason, "status_code": 403 }), content_type="application/json", )
async def _verifyHeader(self, request) -> bool: if request.headers.get("X-Supervisor-Token", None) == self._auth_token: return if request.headers.get("Authorization", None) == "Bearer " + self._auth_token: return raise HTTPUnauthorized()
async def driveRefreshToken(self, request: Request): params = await request.post() if not self.checkClientIdandSecret(params['client_id'], params['client_secret']): raise HTTPUnauthorized() if params['refresh_token'] != self.getSetting('drive_refresh_token'): raise HTTPUnauthorized() if params['grant_type'] != 'refresh_token': raise HTTPUnauthorized() self.generateNewAccessToken() return json_response({ 'access_token': self.settings['drive_auth_token'], 'expires_in': 3600, 'token_type': 'doesn\'t matter' })
async def users_login_get(request: Request) -> Response: session_maker = request.app['db_session_manager'] if 'X-Login' not in request.headers: return HTTPUnauthorized() if not request.headers['X-Login'] == request.match_info['login']: return HTTPForbidden() session: Session = session_maker() try: user = session.query(Users).filter_by( login=request.match_info['login']).first() if not user: return HTTPNotFound() params = request.rel_url.query.get('output') if params: output = [x.strip() for x in params.split(',')] user_serialized = UsersSchema(only=output).dump(user) else: user_serialized = UsersSchema().dump(user) return Response(body=json.dumps(user_serialized), headers={'content-type': 'application/json'}) finally: session.close()
async def validate_token(self, token, permissions=[], raise_error=False): logger.debug( f"validating a token{' for permissions' + permissions if permissions != [] else ''}. Token: {token}" ) user = await find_user_by_token(self.app, token, ["permissions", "username"]) packed = self.branca.decode(token) payload = msgpack.loads(packed, raw=False) logger.debug(f"decoded token: {payload}") if user == None: if raise_error: raise HTTPUnauthorized() return False user_permission_set = set(user.get("permissions", [])) if not set(payload.get("permissions", [])).issubset(user_permission_set): payload["permissions"] = filter( lambda permission: permission in user_permission_set, payload["permissions"], ) if ( # check if token has all requested permissions not set(permissions).issubset(set(payload.get("permissions", []))) # check if user has all requested permissions or not set(permissions).issubset(user_permission_set) ): if raise_error: raise HTTPForbidden() return False logger.debug("Token is valid") return True
async def post(request): """ Handle REST API requests to "/api/logout" First of all, we check that request contains an "Authorization" header with some value, if not - we can't logout user that is not logged in, return an error JSON response. Else, if the JWT token exists, we need to decode it to remove the key from the Redis cache database. If everything is ok, the user successfully logged out. :param request: POST request in JSON representation :return: JSON response """ jwt_token = request.headers.get("Authorization") if not jwt_token: return HTTPUnauthorized() try: jwt_token = jwt_token.split(" ")[1] payload = decode_token(jwt_token) if check_cache(payload) is False: raise ValueError("Token is not active") username = payload.get("name") cache.delitem(username) except ValueError as not_active: return Responses.error(str(not_active)) except Exception: return Responses.error("Token revocation error") finally: return Responses.success("Successfully logged out")
async def statistic_receiver(request: Request): auth = request.headers.get('Authorization') if not auth: raise HTTPUnauthorized() secret = auth.replace("Bearer ", '') if secret != SECRET: raise HTTPForbidden() payload = msgpack.unpackb(await request.read(), encoding='utf-8') if not isinstance(payload, list): raise HTTPBadRequest() for metric in payload: try: name, ts_value = metric ts, value = ts_value ts = float(ts) assert isinstance(value, (int, float, type(None))) except: log.exception("Invalid data in %r", metric) raise HTTPBadRequest() QUEUE.append((name, value, ts)) return Response(content_type='text/plain', status=HTTPStatus.ACCEPTED)
async def auth_middleware(request: Request, handler) -> str: auth_token = request.headers.get('auth') if request.path in public_api_paths or token_is_valid(auth_token): return await handler(request) else: raise HTTPUnauthorized()
async def wrapped(request): # set the area property inside the request object try: user = request.user except AttributeError: # the user of this method is not using it in the intended way raise RuntimeError( "The 'user' property is not set in the request object." "Use the {0}.auth decorator after a '{0}' decorator". format(area_name)) if not user or user.authenticated is False: raise HTTPUnauthorized() if roles and not user.has_any_role(roles): raise HTTPUnauthorized() return await f(request)
async def verify_authn_challenge(request, ctx: AppConfig, session: AuthnSession): if not session.pending_challenge: raise HTTPBadRequest() challenge_response =\ AuthnChallengeResponseRequest.unmarshal_request(await request.json()) if challenge_response.challenge_id != session.pending_challenge.challenge_id: raise ValueError("invalid challenge") session.pending_challenge.attempts += 1 session.changed() if session.pending_challenge.attempts > security.MaxVerificationChallengeAttempts: session.invalidate() raise HTTPForbidden(text="Too many invalid attempts") otp_types = [AuthnChallengeType.Email, AuthnChallengeType.SMS] if session.pending_challenge.challenge_type in otp_types: if challenge_response.passcode != session.pending_challenge.secret: raise HTTPUnauthorized(text="Incorrect passcode") elif session.pending_challenge.challenge_type is AuthnChallengeType.Password: async with op.session(ctx) as ss: result = await op.authn.\ authenticate_user( user_profile_id=session.user_profile_id, password=challenge_response.passcode).\ execute(ss) if not result: raise HTTPUnauthorized(text="Incorrect passcode") else: raise HTTPBadRequest() session.clear_pending_challenge() async with op.session(ctx) as ss: u = await op.user_profile.\ get_user_profile(user_profile_id=session.user_profile_id).\ execute(ss) if session.required_challenges: session.next_challenge_for_user(u) return HTTPAccepted(), session.pending_challenge.get_view('public') session.authenticated = True session.set_role(u.role) session.remove_capabilities(Capability.Authenticate) return HTTPOk()
async def _checkDriveHeaders(self, request: Request): if self.drive_sleep > 0: await asyncio.sleep(self.drive_sleep) self._checkDriveError(request) if request.headers.get( "Authorization", "") != "Bearer " + self.getSetting('drive_auth_token'): raise HTTPUnauthorized()
async def get(self, request: Request): """Handle for GPSLogger message received as GET.""" hass = request.app['hass'] data = request.query if self._password is not None: authenticated = CONF_API_PASSWORD in data and compare_digest( self._password, data[CONF_API_PASSWORD]) if not authenticated: raise HTTPUnauthorized() if 'latitude' not in data or 'longitude' not in data: return ('Latitude and longitude not specified.', HTTP_UNPROCESSABLE_ENTITY) if 'device' not in data: _LOGGER.error("Device id not specified") return ('Device id not specified.', HTTP_UNPROCESSABLE_ENTITY) device = data['device'].replace('-', '') gps_location = (data['latitude'], data['longitude']) accuracy = 200 battery = -1 zone_state = async_active_zone(self.hass, float(data['latitude']), float(data['longitude']), 300) if self._ignore_home and zone_state != None and zone_state.entity_id == zone.ENTITY_ID_HOME: _LOGGER.warn("drop a gps event, because it near home") return if 'accuracy' in data: accuracy = int(float(data['accuracy'])) if 'battery' in data: battery = float(data['battery']) attrs = {} if 'speed' in data: attrs['speed'] = float(data['speed']) if 'direction' in data: attrs['direction'] = float(data['direction']) if 'altitude' in data: attrs['altitude'] = float(data['altitude']) if 'provider' in data: attrs['provider'] = data['provider'] if 'activity' in data: attrs['activity'] = data['activity'] #{{{dylan attrs['update_at'] = int(round(time.time() * 1000)) #}}} hass.async_add_job( self.async_see(dev_id=device, gps=gps_location, battery=battery, gps_accuracy=accuracy, attributes=attrs)) return 'Setting location for {}'.format(device)
async def aiohttp_error_middleware(request, handler): try: response = await handler(request) return response except BotActionNotImplementedError: raise HTTPNotImplemented() except PermissionError: raise HTTPUnauthorized() except KeyError: raise HTTPNotFound() except Exception: raise HTTPInternalServerError()
async def auth_required(request) -> str: # Only expiration date is validated here, # since authenticity of client cert is validated on the TLS level # If request is not secure return early with empty identity. ACL provider will catch # request as unauthorized due to empty client identity. if not request.secure: return "" if await _validate_cert_date(request): identity = await _extract_identity(request) request["identity"] = identity return identity raise HTTPUnauthorized()
async def authenticate(self, request): token = re.sub('^Basic *', '', request.headers.get( 'Authorization', '')) or 'x' try: _, password = base64.b64decode(token).decode().split(':', 1) except (ValueError, UnicodeDecodeError): password = '' if not secrets.compare_digest(password, self.settings.admin_basic_auth_password): raise HTTPUnauthorized(text='Invalid basic auth', headers={'WWW-Authenticate': 'Basic'})
async def get(self, request: Request): """Handle for GPSLogger message received as GET.""" hass = request.app['hass'] data = request.query if self._password is not None: authenticated = CONF_API_PASSWORD in data and compare_digest( self._password, data[CONF_API_PASSWORD] ) if not authenticated: raise HTTPUnauthorized() if 'latitude' not in data or 'longitude' not in data: return ('Latitude and longitude not specified.', HTTP_UNPROCESSABLE_ENTITY) if 'device' not in data: _LOGGER.error("Device id not specified") return ('Device id not specified.', HTTP_UNPROCESSABLE_ENTITY) device = data['device'].replace('-', '') gps_location = (data['latitude'], data['longitude']) accuracy = 200 battery = -1 if 'accuracy' in data: accuracy = int(float(data['accuracy'])) if 'battery' in data: battery = float(data['battery']) attrs = {} if 'speed' in data: attrs['speed'] = float(data['speed']) if 'direction' in data: attrs['direction'] = float(data['direction']) if 'altitude' in data: attrs['altitude'] = float(data['altitude']) if 'provider' in data: attrs['provider'] = data['provider'] if 'activity' in data: attrs['activity'] = data['activity'] hass.async_add_job(self.async_see( dev_id=device, gps=gps_location, battery=battery, gps_accuracy=accuracy, attributes=attrs )) return 'Setting location for {}'.format(device)
async def delete_entries(request): if not compare_digest(request.match_info['token'], request.app['settings'].update_token): raise HTTPUnauthorized(text='invalid token\n') async with request.app['db'].acquire() as conn: entries_before = await conn.fetchval('SELECT COUNT(*) from entries') logger.info('entries before: %d', entries_before) await conn.execute('DELETE FROM entries') return Response( text=f'all entries deleted, entries before: {entries_before}', content_type='text/plain')
async def api(request): """Check headers for authorization, load JSON/query data and return as JSON.""" if not request.headers.get('authorization'): raise HTTPUnauthorized() return json_response({ 'params': { 'user': int(request.match_info['user']), 'record': int(request.match_info['record']), }, 'query': dict(request.query), 'data': await request.json(), })
def middleware(request): if 'AUTHORIZATION' not in request.headers: raise HTTPUnauthorized( headers={'WWW-Authenticate': 'Basic realm="flowpanel"'} ) else: auth, loginpassword = request.headers['AUTHORIZATION'].split(" ", 2) assert auth == "Basic" login, password = b64decode(loginpassword).decode('utf-8').split(':', 2) # FIXME, validate the password request[USER_KEY] = login return (yield from handler(request))
async def validate_token(self, token, permissions=None, raise_error=False): """Validate if token is valid and has the requested permissions. Parameters ---------- token : str The token to be validated permissions : list(str), default=None The permissions that the token must have access to. raise_error : bool, default=False If True, raise an error if the token is invalid, otherwise just return False Returns ------- bool True if the token is valid and has the requested permissions, False otherwise """ permissions = permissions if permissions else [] logger.debug( "validating a token%s. Token: %s", " for permissions" + permissions if permissions != [] else "", token, ) user = await find_user_by_token(self.app, token, ["permissions", "username"]) packed = self.branca.decode(token) payload = msgpack.loads(packed, raw=False) logger.debug("decoded token: %s", payload) if user is None: if raise_error: raise HTTPUnauthorized() return False user_permission_set = set(user.get("permissions", [])) if not set(payload.get("permissions", [])).issubset(user_permission_set): payload["permissions"] = filter( lambda permission: permission in user_permission_set, payload["permissions"], ) if ( # check if token has all requested permissions not set(permissions).issubset( set(payload.get("permissions", []))) # check if user has all requested permissions or not set(permissions).issubset(user_permission_set)): if raise_error: raise HTTPForbidden() return False logger.debug("Token is valid") return True
async def aiohttp_error_middleware(request, handler): try: response = await handler(request) return response except BotActionNotImplementedError: raise HTTPNotImplemented() except NotImplementedError: raise HTTPNotImplemented() except PermissionError: raise HTTPUnauthorized() except KeyError: raise HTTPNotFound() except HTTPError as error: # In the case the integration adapter raises a specific HTTPError raise error except Exception: raise HTTPInternalServerError()
async def login(request): next_url = request.query.get('next', '/') LOG.debug('next URL: %s', next_url) request_session = await get_session(request) access_token = request_session.get('access_token') if access_token: # Redirect only if the token is valid await get_user_info_and_redirect(access_token, next_url, request_session) # Otherwise, we don't have a token (yet) # A redirect response will be raised await do_login(request, request_session, next_url) # If we reach here, we have an invalid token, even after creating it raise HTTPUnauthorized(reason='Failed to obtain access token.')
async def _http_authenticate_request(self, request: Request) -> bool: # pylint: disable=no-member try: if not await self._credential_provider.is_authentication_disabled( ): auth_header = request.headers.get(self._AUTH_HEADER_NAME) channel_id = request.headers.get(self._CHANNEL_ID_HEADER_NAME) if not auth_header: await self._write_unauthorized_response( self._AUTH_HEADER_NAME) return False if not channel_id: await self._write_unauthorized_response( self._CHANNEL_ID_HEADER_NAME) return False claims_identity = await JwtTokenValidation.validate_auth_header( auth_header, self._credential_provider, self._channel_provider, channel_id, ) if not claims_identity.is_authenticated: raise HTTPUnauthorized() self._credentials = ( self._credentials or await self._BotFrameworkAdapter__get_app_credentials( self.settings.app_id, AuthenticationConstants. TO_CHANNEL_FROM_BOT_OAUTH_SCOPE, )) # Add ServiceURL to the cache of trusted sites in order to allow token refreshing. self._credentials.trust_service_url( claims_identity.claims.get( AuthenticationConstants.SERVICE_URL_CLAIM)) self.claims_identity = claims_identity return True except Exception as error: raise error
async def wrapped(*args, **kwargs): if middlewares.request_property is ...: raise RuntimeError('Incorrect usage of decorator.' 'Please initialize middleware first') request = args[-1] if isinstance(request, View): request = request.request if not isinstance(request, BaseRequest): # pragma: no cover raise RuntimeError( 'Incorrect usage of decorator.' 'Expect web.BaseRequest as an argument') if not request.get(middlewares.request_property): raise HTTPUnauthorized(reason='Authorization required') session_id = (await get_from_cache(request.app['cache'], key=request['token'])) if not session_id or session_id.decode('utf8') != request.cookies.get('sessionID'): raise HTTPForbidden(reason='Session has expired') return await func(*args, **kwargs)
async def post(self) -> Response: """Authorize route function.""" db = self.request.app["db"] try: body = await self.request.json() except json.decoder.JSONDecodeError as e: raise HTTPBadRequest(reason="Invalid data in request body.") from e # Process: try: await AuthorizationService.authorize(db, body.get("token", None), body.get("roles", None)) except ( InvalidTokenException, InvalidInputException, IncompleteTokenException, ) as e: logging.debug(traceback.format_exc()) raise HTTPUnauthorized(reason=str(e)) from e except (UserNotAuthorizedException, InconsistentTokenException) as e: raise HTTPForbidden(reason=str(e)) from e return Response(status=204)
async def init_authn_session(request, ctx: AppConfig, session: AuthnSession): sr = InitiateAuthnSessionRequest.unmarshal_request(await request.json()) async with op.session(ctx) as ss: if sr.principal_type is AuthnPrincipalType.Email: u = await op.user_profile.get_user_profile( email_address=sr.principal_name).execute(ss) session.require_challenge(AuthnChallengeType.Email) elif sr.principal_type is AuthnPrincipalType.Phone: u = await op.user_profile.get_user_profile( phone_number=sr.principal_name).execute(ss) session.require_challenge(AuthnChallengeType.SMS) else: raise ValueError(sr.principal_type) if u is None: raise HTTPUnauthorized() session.user_profile_id = u.user_profile_id if u.role in {UserRole.Superuser, UserRole.Manager, UserRole.Creator}: session.require_challenge(AuthnChallengeType.Password) session.add_capabilities(Capability.Authenticate) return HTTPOk()
async def _connect_web_socket(self, bot: Bot, request: Request, ws_response: WebSocketResponse): if not request: raise TypeError("request can't be None") if ws_response is None: raise TypeError("ws_response can't be None") if not bot: raise TypeError( f"'bot: {bot.__class__.__name__}' argument can't be None") if not ws_response.can_prepare(request): raise HTTPBadRequest(text="Upgrade to WebSocket is required.") if not await self._http_authenticate_request(request): raise HTTPUnauthorized(text="Request authentication failed.") try: await ws_response.prepare(request) bf_web_socket = AiohttpWebSocket(ws_response) request_handler = StreamingRequestHandler(bot, self, bf_web_socket) if self.request_handlers is None: self.request_handlers = [] self.request_handlers.append(request_handler) await request_handler.listen() except Exception as error: import traceback # pylint: disable=import-outside-toplevel traceback.print_exc() raise Exception( f"Unable to create transport server. Error: {str(error)}")
async def update(request): if not compare_digest(request.match_info['token'], request.app['settings'].update_token): raise HTTPUnauthorized(text='invalid token\n') r = StreamResponse() r.content_type = 'text/html' await r.prepare(request) divider = '>' if 'html' in request.headers.get('Accept', ''): divider = '>' await r.write(STREAM_HEAD) async def log(msg): logger.info(msg) try: await r.write( f'{datetime.now():%H:%M:%S} {divider} {msg}\n'.encode()) except RuntimeError as e: logger.warning('unable to write to response: %s', e) start, finish = int(request.match_info['start']), int( request.match_info['finish']) await update_index(start, finish, request.app['db'], log) return r