def verify_core_token(group_name=None): id_token = get_bearer_token(request) if not id_token: raise OAuthProblem('Missing id token') # check if its the rokwire core issuer unverified_header, unverified_payload = get_unverified_header_payload( id_token) ROKWIRE_AUTH_HOST = os.getenv('ROKWIRE_AUTH_HOST', '') ROKWIRE_AUTH_KEY_PATH = os.getenv('ROKWIRE_AUTH_KEY_PATH', '') issuer = unverified_payload.get('iss') kid = unverified_header.get('kid') if not kid: logger.warning("kid not found. Aborting.") raise OAuthProblem('Invalid token') if issuer == ROKWIRE_AUTH_HOST: keyset = get_keyset(ROKWIRE_AUTH_HOST + ROKWIRE_AUTH_KEY_PATH) target_client_ids = re.split(',', (os.getenv('ROKWIRE_AUTH_AUD', '')).replace(" ", "")) id_info = decode_id_token(id_token, keyset, target_client_ids, kid) g.user_token_data = id_info g.user_token = id_token return {'id_token_valid': True} else: raise OAuthProblem('invalid core token')
def validate_claim( token_info: Claim, dataset_id: DatasetId, permissions: List[DatasetPermission], organization_id: Optional[OrganizationId] = None, ) -> AuthContext: # API v1 does not specify an organization. Additionally, for v1 API # compatability, we assume the organization of context is the head # organization in the given JWT claim: if organization_id is None: if token_info.head_organization_node_id is None: raise OAuthProblem("Missing organization node id") organization_int_id: OrganizationId = OrganizationId( token_info.head_organization_id.id ) else: organization_int_id = OrganizationId(organization_id) dataset_int_id = dataset_id if token_info.is_user_claim: if token_info.content.node_id is None: raise OAuthProblem("Missing user node ID") user_node_id = UserNodeId(token_info.content.node_id) else: user_node_id = SERVICE_USER_NODE_ID auth_organization_id = RoleOrganizationId(organization_int_id) auth_dataset_id = RoleDatasetId(dataset_int_id) if not token_info.has_organization_access(auth_organization_id): raise Forbidden for permission in permissions: if not token_info.has_dataset_access(auth_dataset_id, permission): raise Forbidden # (invariant): # These roles should never be None and are assumed to be valid given the # checks above. organization_role = token_info.get_role(auth_organization_id) dataset_role = token_info.get_role(auth_dataset_id) def get_locked(): for role in token_info.content.roles: # we do not pass through the locked field for a wildcard role, # since by definition the wildcard means we don't know individual datasets are locked or not if role.id == auth_dataset_id and isinstance(role, DatasetRole): return role.locked return None return AuthContext( organization_id=organization_int_id, dataset_id=dataset_id, user_node_id=user_node_id, organization_node_id=organization_role.node_id, dataset_node_id=dataset_role.node_id, locked=get_locked(), )
def auth_token(token, required_scopes): db_token = db.session.query(Token) \ .filter(Token.uuid == token).first() if not db_token: raise OAuthProblem(TOKEN_NOT_FOUND_MSG) if not db_token.is_open: raise OAuthProblem(TOKEN_CLOSED_MSG) return {'sub': db_token.uuid}
def check_app_key(api_key, required_scopes): if api_key == "": raise OAuthProblem('Please provide app token!') db = pymysql.connect(db=config('sqlUser'), user=config('sqlUser'), passwd=config('sqlPass'), host='localhost', port=3306) cursor=db.cursor(pymysql.cursors.DictCursor) sql="SELECT * FROM Core_RESTAPI.v5__vw_App_Keys WHERE 1=1 AND app_key = %s;" cursor.execute(sql,(api_key,)) results=cursor.fetchone() cursor.close() db.close() if not results: raise OAuthProblem('App Key Invalid') if not api_key == results['app_key']: raise OAuthProblem('App Key Invalid') if results['locked'] == 1: raise OAuthProblem('The account associated with the supplied APP key is locked') if results['banned'] == 1: raise OAuthProblem('The account associated with the supplied APP key has been banned') if results['expired'] == 1: raise OAuthProblem('This APP key has expired') if results['blocked'] == 1: raise OAuthProblem('This APP key has been blocked') if results['revoked'] == 1: raise OAuthProblem('This APP key has been revoked') if results['compromised'] == 1: raise OAuthProblem('This APP key has been compromised') return {'uid': results}
def get_bearer_token(request): auth_header = request.headers.get('Authorization') if not auth_header: logger.warning("Request missing Authorization header") raise OAuthProblem('Missing authorization header') ah_split = auth_header.split() if len(ah_split) != 2 or ah_split[0].lower() != 'bearer': logger.warning("invalid auth header. expecting 'bearer' and token with space between") raise OAuthProblem('Invalid request header') _id_token = ah_split[1] return _id_token
def verify_secret(request): key = request.headers.get(rokwire_api_key_header) if not key: logger.warning("Request missing the " + rokwire_api_key_header + " header") raise OAuthProblem('Missing API Key') # missing header means bad request # Assumption is that the key is a comma separated list of uuid's # This simply turns it in to a list and iterates. If the supplied key is in this list, true is returned # Otherwise, an error is raised. keys = os.getenv('ROKWIRE_API_KEY').strip().split(',') for test_key in keys: if key == test_key.strip(): # just in case there are embedded blanks return True raise OAuthProblem('Invalid API Key') # failed matching means unauthorized in this context.
def verify_apikey(key, required_scopes=None): if not key: logger.warning("API key is missing the " + rokwire_api_key_header + " header") raise OAuthProblem('Missing API Key') # Assumption is that the key is a comma separated list of uuid's # This simply turns it in to a list and iterates. If the supplied key is in this list, true is returned # Otherwise, an error is raised. keys = os.getenv('ROKWIRE_API_KEY').strip().split(',') for test_key in keys: if key == test_key.strip(): # just in case there are embedded blanks return {'token_valid': True} else: raise OAuthProblem('Invalid API Key')
def wrapper(*args, **kwargs): logger.debug("%s Oauth verification...", request.url) authorization = request.headers.get('Authorization') # type: str # check if session authenticated user is_authenticated = flask_session.get('is_authenticated') user = flask_session.get('user') token = flask_session.get('access_token') if not authorization and not token: logger.info("... No auth provided. Aborting with 401.") raise OAuthProblem(description='No authorization token provided') if not all([user, is_authenticated, token]): if not token: try: _, token = authorization.split() # type: str, str except ValueError: raise OAuthProblem( description='Invalid authorization header') token_info = fetch_token_info(token_info_url, token) user_scopes = set(token_info['scope']) logger.debug("... Scopes required: %s", allowed_scopes) logger.debug("... User scopes: %s", user_scopes) if not allowed_scopes <= user_scopes: logger.info( textwrap.dedent(""" ... User scopes (%s) do not match the scopes necessary to call endpoint (%s). Aborting with 403.""").replace('\n', ''), user_scopes, allowed_scopes) raise OAuthScopeProblem( description= 'Provided token doesn\'t have the required scope', required_scopes=allowed_scopes, token_scopes=user_scopes) logger.info("... Token authenticated.") request.user = token_info.get('uid') request.token_info = token_info set_token_info(token_info) return function(*args, **kwargs)
def auth(api_key, required_scopes): print(trialstreamer.config.API_KEYS) print(api_key) info = trialstreamer.config.API_KEYS.get(api_key, None) if not info: raise OAuthProblem('Invalid token') return info
def apikey_auth(token, required_scopes): try: user = db.find_user_by_authorization(token) except NotFoundError: raise OAuthProblem("Invalid token") return {"uid": user.uid}
def apikey_auth(token, required_scopes): validate = TOKEN_DB.get(token, None) if not validate: log('Invalid token', 'critical') raise OAuthProblem('Invalid token!') log(f'User Logged: {validate}') return validate
def basic_auth(username, password, required_scopes=None): if username == USER_DB.get('username') and password == USER_DB.get( 'password'): return {'sub': 'admin'} else: raise OAuthProblem('Invalid username or password') return None
def apikey_auth(token, required_scopes): info = TOKEN_DB.get(token, None) if not info: raise OAuthProblem('Invalid token') return info
def get_keyset(request_url): keyset_resp = requests.get(request_url) if keyset_resp.status_code != 200: logger.warning("bad status getting keyset. status code = %s" % keyset_resp.status_code) raise OAuthProblem('Invalid token') keyset = keyset_resp.json() return keyset
def apikey_auth(apikey, required_scopes=None): """ Simple function to validate an API key and retrieve the user's information in the process """ api_user = User.query.filter_by(api_token=apikey).first() if api_user is None: raise OAuthProblem('Invalid API key') return api_user
def authorize(group_name=None): if 'user_token_data' not in g: raise OAuthProblem('Token data not available for authorization. Most likely an authentication error.') else: id_info = g.user_token_data if group_name is not None: # So we are to check is a group membership is required. if uiucedu_is_member_of in id_info: is_member_of = id_info[uiucedu_is_member_of] print("is_member_of" + str(is_member_of)) if group_name not in is_member_of: logger.warning("user is not a member of the group " + group_name) raise OAuthProblem('Invalid token') else: logger.warning(uiucedu_is_member_of + " field is not present in the ID Token") raise OAuthProblem('Invalid token')
def wrapper(request): authorized_domains = Config.get_allowed_email_domains().split() if "token_info" in request.context.values: token_info = request.context.values["token_info"] if not int(token_info["expires_in"]) > 0: raise OAuthProblem( description="Authorization token has expired") if json.loads(token_info["email_verified"]) is not True: raise OAuthProblem( description="User's email is not verified") if self.testing_403 or not any( token_info["email"].endswith("@" + ad) for ad in authorized_domains): raise Forbidden( description= "User is not authorized to access this resource") return function(request)
def verify_apikey(token, required_scopes): """Helper function to verify provided TOKEN with REQUIRED_SCOPES.""" config = current_app.config TOKEN_DB = config["api_tokens"] info = TOKEN_DB.get(token, None) if not info: raise OAuthProblem( "Invalid token provided, please authorize with CORRECT Api-key!") return info
def apikey_auth(token, required_scopes): # info = TOKEN_DB.get(token, None) user = db.session.query(TolidUser) \ .filter(TolidUser.api_key == token) \ .one_or_none() if user is None: raise OAuthProblem('Invalid api-key token') return {"user": user.name, "uid": user.user_id}
def get_unverified_header_payload(id_token): try: # We need to get both the header and the payload initially as unverified since we have to # check their issuer, key id and a few other items before we can figure out how to unpack them unverified_header = jwt.get_unverified_header(id_token) unverified_payload = jwt.decode(id_token, verify=False) except jwt.exceptions.PyJWTError as jwte: logger.warning("jwt error on get unverified header. message = %s" % jwte) raise OAuthProblem('Invalid token') return unverified_header, unverified_payload
def decode_id_token(id_token, keyset, target_client_ids, kid): matching_jwks = [ key_dict for key_dict in keyset['keys'] if key_dict['kid'] == kid ] if len(matching_jwks) != 1: logger.warning("should have exactly one match for kid = %s" % kid) raise OAuthProblem('Invalid token') jwk = matching_jwks[0] pub_key = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(jwk)) try: id_info = jwt.decode(id_token, key=pub_key, audience=target_client_ids, verify=True) except jwt.exceptions.PyJWTError as jwte: logger.warning("jwt error on decode. message = %s" % jwte) raise OAuthProblem('Invalid token') if not id_info: logger.warning("id_info was not returned from decode") raise OAuthProblem('Invalid token') return id_info
def authenticate(group_name=None, internal_token_only=False): should_use_security_token_auth = False app = flask.current_app if request.endpoint in app.view_functions: view_func = app.view_functions[request.endpoint] should_use_security_token_auth = getattr(view_func, '_use_security_token_auth', False) # print("should use security token auth = %s" % should_use_security_token_auth) auth_header = request.headers.get('Authorization') if not auth_header: logger.warning("Request missing Authorization header") raise OAuthProblem('Missing authorization header') ah_split = auth_header.split() if len(ah_split) != 2 or ah_split[0].lower() != 'bearer': logger.warning("invalid auth header. expecting 'bearer' and token with space between") raise OAuthProblem('Invalid request header') _id_token = ah_split[1] id_info = verify_userauth(_id_token, group_name, internal_token_only) return id_info
def check_auth_key(api_key, required_scopes): if api_key == "": raise OAuthProblem('Please provide app token!') db = pymysql.connect(db=config('sqlUser'), user=config('sqlUser'), passwd=config('sqlPass'), host='localhost', port=3306) cursor=db.cursor(pymysql.cursors.DictCursor) sql="SELECT * FROM Core_RESTAPI.v5__vw_Auth_Keys WHERE 1=1 AND auth_key = %s;" cursor.execute(sql,(api_key,)) authresults=cursor.fetchone() cursor.close() db.close() if not authresults: raise OAuthProblem('Auth Key Invalid') if authresults['blocked'] == 1: raise OAuthProblem('This Auth key has been blocked') if authresults['expired'] == 1: raise OAuthProblem('This Auth key has expired') if authresults['revoked'] == 1: raise OAuthProblem('This Auth key has been revoked') if authresults['compromised'] == 1: raise OAuthProblem('This Auth key has been compromised') app_key=authresults['app_key'] get_appresults=check_app_key(app_key,'') appresults=get_appresults['uid'] return {'uid': {'app': appresults, 'auth': authresults}}
def verify_userauth_coretoken(group_name=None): id_token = get_bearer_token(request) if not id_token: raise OAuthProblem('Missing id token') # check which token auth verify to use unverified_header, unverified_payload = get_unverified_header_payload( id_token) isAnonymous = unverified_payload.get('anonymous') if isAnonymous == True: return verify_core_token(group_name) return verify_core_userauth(id_token, group_name)
def authorize(group_name=None): if 'user_token_data' not in g: raise OAuthProblem( 'Token data not available for authorization. Most likely an authentication error.' ) else: id_info = g.user_token_data if group_name is not None: ROKWIRE_AUTH_HOST = os.getenv('ROKWIRE_AUTH_HOST', '') # So we are to check is a group membership is required. # Get the membership check keys based on issuer if id_info['iss'] == ROKWIRE_AUTH_HOST: is_member_of_key = is_member_of_claim else: is_member_of_key = uiucedu_is_member_of # check if the group_name is list or string if isinstance(group_name, str): # make group name as list group_name = [group_name] is_authorize = False if is_member_of_key in id_info: is_member_of = id_info[is_member_of_key] if is_member_of_key == is_member_of_claim: is_member_of = is_member_of.split(',') for name in group_name: if id_info['iss'] != ROKWIRE_AUTH_HOST: name = ROKWIRE_GROUPS_MAP[name] if name in is_member_of: is_authorize = True break if is_authorize is False: logger.warning("User not authorized.") raise OAuthProblem('Invalid token')
def token_info(access_token) -> dict: token = access_token jsonurl = urlopen("https://" + AUTH0_DOMAIN + "/.well-known/jwks.json") jwks = json.loads(jsonurl.read()) unverified_header = jwt.get_unverified_header(token) rsa_key = {} for key in jwks["keys"]: if key["kid"] == unverified_header["kid"]: rsa_key = { "kty": key["kty"], "kid": key["kid"], "use": key["use"], "n": key["n"], "e": key["e"] } if rsa_key: try: payload = jwt.decode(token, rsa_key, algorithms=ALGORITHMS, audience=API_AUDIENCE, issuer="https://" + AUTH0_DOMAIN + "/") except jwt.ExpiredSignatureError: raise OAuthProblem('Token is expired', 401) except jwt.JWTClaimsError: raise OAuthProblem( 'Invalid claims. Please check the audience and issuer', 401) except Exception: raise OAuthProblem('Invaid token - unable to parse authentication', 401) _request_ctx_stack.top.current_user = payload return {'uid': payload['sub'], 'scope': payload['scope']}
def verify_githubauth(token_str): id_info = None if not token_str: logger.warning("Request missing id token") raise OAuthProblem('Missing id token') try: access_token = { 'access_token': token_str, 'token_type': 'bearer', 'scope': [''] } github = OAuth2Session(GITHUB_CLIENT_ID, token=access_token) resp = github.get('https://api.github.com/user') if resp.status_code == 200: id_info = resp.json() print(id_info) else: logger.warning("The token provides is invalid") raise OAuthProblem('Invalid token') except: logger.warning("The token provides is invalid") raise OAuthProblem('Invalid token') return id_info
def info_from_ApiKeyAuth(api_key, required_scopes): """ Check and retrieve authentication information from api_key. Returned value will be passed in 'token_info' parameter of your operation function, if there is one. 'sub' or 'uid' will be set in 'user' parameter of your operation function, if there is one. :param api_key API key provided by Authorization header :type api_key: str :param required_scopes Always None. Used for other authentication method :type required_scopes: None :return: Information attached to provided api_key or None if api_key is invalid or does not allow access to called API :rtype: dict | None """ info = TOKEN_DB.get(api_key, None) current_app.logger.debug("{} -- {} -- {}".format(info, api_key, TOKEN_DB)) if not info: raise OAuthProblem('Invalid token') return info
def authorize_search(organization_id: int, trace_id: TraceId, token_info: Claim): if not token_info.is_user_claim: raise OAuthProblem("Requires a user claim") if not token_info.has_organization_access( RoleOrganizationId(organization_id)): raise Forbidden user_id = UserId(token_info.content.node_id) datasets = PennsieveApiClient.get().get_datasets( headers=dict(**auth_header(), **with_trace_id_header(trace_id))) return SearchDatabase( db=current_app.config["db"], organization_id=organization_id, user_id=user_id, datasets=datasets, )
async def _extract_token(self, token: str) -> Dict[str, Any]: if token == "null": return {"sub": self._default_user_id} try: unverified_header = jwt.get_unverified_header(token) except jwt.JWTError as e: raise OAuthProblem( description= "Invalid header: %s. Use an RS256 signed JWT Access Token." % e) if unverified_header["alg"] != "RS256": raise OAuthProblem( description= "Invalid algorithm %s. Use an RS256 signed JWT Access Token." % unverified_header["alg"]) kids = await self.kids() try: rsa_key = kids[unverified_header["kid"]] except KeyError: raise OAuthProblem( description="Unable to find the matching Auth0 RSA public key") try: return jwt.decode( token, rsa_key, algorithms=["RS256"], audience=self._audience, issuer="https://%s/" % self._domain, ) except jwt.ExpiredSignatureError as e: raise OAuthProblem(description="JWT expired: %s" % e) except jwt.JWTClaimsError as e: raise OAuthProblem(description="invalid claims: %s" % e) except jwt.JWTError as e: raise OAuthProblem( description="Unable to parse the authentication token: %s" % e)