def is_valid_token(self): credentials = self.__parse_token(); username = credentials[1] pwd = credentials[2] keycloak = KeyCloak(server_url="https://auth.s2s-omxware.us-south.containers.appdomain.cloud/auth/", client_id="omx-zeppelin", realm_name="omxware", client_secret_key="c05b7553-cf21-4f0c-ab81-a38aca3ba172", verify=False) if self.__env != 'public': keycloak = KeyCloak(server_url="https://omx-auth.sl.cloud9.ibm.com/auth/", client_id="omx-zeppelin", realm_name="omxware", client_secret_key="1320e78d-025d-48eb-ad3e-451281786932", verify=False) try: # Get Token token = keycloak.token(username, pwd) self.__userinfo = keycloak.userinfo(token['access_token']) self.__keycloak_token = token['access_token'] return True except KeycloakAuthenticationError as auth_error: # Exception object looks like this # keycloak.exceptions.KeycloakAuthenticationError: # 401: b'{"error":"invalid_grant","error_description":"Invalid user credentials"}' error_msg = '' if auth_error['error_description'] != None: error_msg = auth_error['error_description'] if error_msg.strip() != None: print(error_msg) else: print(auth_error['error_description']) return False
realm_name="wienernetze", client_secret_key=uuid.uuid1()) try: token = keycloak_openid.token(USERNAME, PASSWORD) except: try: print('[' + str(sys.exc_info()[1]).split(":")[0] + '] ' + requests.status_codes._codes[int( str(sys.exc_info()[1]).split(":")[0])][0]) except: print("Network ERROR") print(" ") sys.exit() userinfo = keycloak_openid.userinfo(token['access_token']) print('[200] ' + str(userinfo)) print(" ") print("===============") print("=== OPTIONS ===") print("===============") print(" ") URL = "https://service.wienernetze.at/rest/smp/1.0/m/messdaten/zaehlpunkt/" + ZNR + "/verbrauch" URL += "?dateFrom=" + from_date_utc.isoformat() + ".000Z" URL += "&period=DAY&accumulate=false&offset=0&dayViewResolution=QUARTER-HOUR" headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux ppc64le; rv:66.0) Gecko/20100101 Firefox/66.0',
class Keycloak: """Keycloak authentication class.""" def get_keycloak_user_token(self, tenant: AnyStr, password: AnyStr) -> Dict: """ Get the token of the user authentication in Keycloak. :tenant (AnyStr) the user username :password (AnyStr) the user password Return the keycloak user token if valid credentials. """ keycloak_openid = self.client token = None try: token = keycloak_openid.token(tenant, password) if envvar('GRAFANA') == 'true': user_grafana = grafana.get_grafana_user(tenant) if not user_grafana: grafana.create_grafana_user(tenant, password) if self.verify_group_admin(): grafana.update_grafana_role(user_grafana, 'Editor') except exceptions.KeycloakAuthenticationError or exceptions.KeycloakGetError: logging.error(f'Authentication error for user {tenant}') finally: return token def client(self, **kwargs: Dict) -> KeycloakOpenID: """ Create an authenticated keycloak client. :kwargs (Dict) A directory contaning the keycloak client authentication credentials Return the KeycloakOpenID object. """ config = {} if kwargs: config.update(kwargs) else: config.update({ 'server_url': envvar('KEYCLOAK_URL'), 'client_id': envvar('KEYCLOAK_CLIENT_ID'), 'realm_name': envvar('KEYCLOAK_REALM'), 'client_secret_key': envvar('KEYCLOAK_SECRET_KEY') }) self.client = KeycloakOpenID(**config) return self.client def verify(self, tenant: AnyStr, password: AnyStr) -> bool: """ Verify if a user token is not empty. :tenant (AnyStr) the user username :password (AnyStr) the user password Return a boolean describing the success of the user verification in keycloak. """ if tenant == envvar('ADMIN_ACCOUNT'): if password == envvar('GRAFANA_ADMIN_PASSWORD'): return True else: return False else: return self.get_token(tenant, password) def verify_group_admin(self, **kwargs: Dict) -> bool: """ Check if a user is admin. Return a boolean to express if a user is admin or no. """ tenant_info = self.get_infos() group = tenant_info.get('group', '') if group == 'admin': return True else: return False def get_infos(self) -> Any: """Verify users information.""" return self.client.userinfo(self.token['access_token']) def get_token(self, tenant: AnyStr, password: AnyStr) -> Dict: """ Get the token of the user authentication in Keycloak. :tenant (AnyStr) the user username :password (AnyStr) the user password """ self.token = self.get_keycloak_user_token(tenant, password) return self.token def get_namespace(self, **kwargs: Dict) -> AnyStr: """ Get the user namespaces attribute from the token. Return the user namespaces. """ tenant_info = self.get_infos() return tenant_info.get('namespaces', '')
#!/usr/bin/env python3 from keycloak import KeycloakOpenID keycloak_openid = KeycloakOpenID( server_url='http://localhost:8080/auth/', client_id='romi-dashboard', realm_name='master' ) token = keycloak_openid.token('admin', 'admin') user_id = keycloak_openid.userinfo(token['access_token'])['sub'] user_name = keycloak_openid.userinfo(token['access_token'])['preferred_username'] print(f'user ID: {user_id}') print(f'user name: {user_name}') #import requests # todo: stuff the token into the request headers #headers = {'foo': 'bar'} #r = requests.get('http://localhost:5000', headers=headers) #print(r.text)
class KeycloakMiddleware(MiddlewareMixin): def __init__(self, get_response): """ :param get_response: """ self.config = settings.APPLICATION_CONFIG # Read configurations try: self.server_url = get_application_config_for_key('KEYCLOAK_SERVER_URL') self.client_id = get_application_config_for_key('KEYCLOAK_CLIENT_ID') self.realm = get_application_config_for_key('KEYCLOAK_REALM') except KeyError as e: raise Exception("KEYCLOAK_SERVER_URL, KEYCLOAK_CLIENT_ID or KEYCLOAK_REALM not found.") self.client_secret_key = get_application_config_for_key('KEYCLOAK_CLIENT_SECRET_KEY') self.default_access = get_application_config_for_key('KEYCLOAK_DEFAULT_ACCESS') self.method_validate_token = get_application_config_for_key('KEYCLOAK_METHOD_VALIDATE_TOKEN') self.keycloak_authorization_config = get_application_config_for_key('KEYCLOAK_AUTHORIZATION_CONFIG') # Create Keycloak instance self.keycloak = KeycloakOpenID(server_url=self.server_url, client_id=self.client_id, realm_name=self.realm, client_secret_key=self.client_secret_key, ) # Read policies if self.keycloak_authorization_config: self.keycloak.load_authorization_config(self.keycloak_authorization_config) # Django self.get_response = get_response print("KEYCLOAK_SERVER URL", get_application_config_for_key('KEYCLOAK_SERVER_URL')) print("KEYCLOAK_CLIENT_ID URL", get_application_config_for_key('KEYCLOAK_CLIENT_ID')) print("KEYCLOAK_REALM URL", get_application_config_for_key('KEYCLOAK_REALM')) @property def keycloak(self): return self._keycloak @keycloak.setter def keycloak(self, value): self._keycloak = value @property def config(self): return self._config @config.setter def config(self, value): self._config = value @property def server_url(self): return self._server_url @server_url.setter def server_url(self, value): self._server_url = value @property def client_id(self): return self._client_id @client_id.setter def client_id(self, value): self._client_id = value @property def client_secret_key(self): return self._client_secret_key @client_secret_key.setter def client_secret_key(self, value): self._client_secret_key = value @property def client_public_key(self): return self._client_public_key @client_public_key.setter def client_public_key(self, value): self._client_public_key = value @property def realm(self): return self._realm @realm.setter def realm(self, value): self._realm = value @property def keycloak_authorization_config(self): return self._keycloak_authorization_config @keycloak_authorization_config.setter def keycloak_authorization_config(self, value): self._keycloak_authorization_config = value @property def method_validate_token(self): return self._method_validate_token @method_validate_token.setter def method_validate_token(self, value): self._method_validate_token = value def __call__(self, request): """ :param request: :return: """ return self.get_response(request) def process_view(self, request, view_func, view_args, view_kwargs): """ Validate only the token introspect. :param request: django request :param view_func: :param view_args: view args :param view_kwargs: view kwargs :return: """ print ('DEBUG:', request) # do not block the access to root! if request.path_info == '/': logger.debug('** exclude path found, skipping') return None # CONTINGENCY SOLUTION!!! review API to avoid this # if request.path_info[-7:] == '/series': # return None whitelist = [ '/api/v1/api', '/api/v1/alive', '/api/v1/ready', '/oformat/WORD/documentation', '/oformat/EXCEL/documentation', '/export_download' ] for iwhite in whitelist: if request.path_info.endswith(iwhite): print ('skipped:', request.path_info) return None if hasattr(settings, 'KEYCLOAK_BEARER_AUTHENTICATION_EXEMPT_PATHS'): path = request.path_info.lstrip('/') if any(re.match(m, path) for m in settings.KEYCLOAK_BEARER_AUTHENTICATION_EXEMPT_PATHS): logger.debug('** exclude path found, skipping') return None try: roles = view_func.cls.roles except AttributeError as e: return JsonResponse({"detail": NotAuthenticated.default_detail}, status=NotAuthenticated.status_code) if 'HTTP_AUTHORIZATION' not in request.META: return JsonResponse({"detail": NotAuthenticated.default_detail}, status=NotAuthenticated.status_code) auth_header = request.META.get('HTTP_AUTHORIZATION').split() token = auth_header[1] if len(auth_header) == 2 else auth_header[0] try: userinfo = self.keycloak.userinfo(token) except KeycloakError as e: return JsonResponse({"detail": AuthenticationFailed.default_detail}, status=AuthenticationFailed.status_code) has_role = True for role in roles: if role not in userinfo['groups']: has_role = False # In case we need to verify token. But since we verify it by using userinfo call, it is not necessary atm. # KEYCLOAK_PUBLIC_KEY = self.client_public_key # options = {"verify_signature": True, "verify_aud": True, "verify_exp": True} # token_info = self.keycloak.decode_token(token, key=KEYCLOAK_PUBLIC_KEY, options=options) # if token_info['realm_access'] and token_info['realm_access']['roles']: # print(token_info['realm_access']['roles']) if has_role: return None # User Permission Denied return JsonResponse({"detail": PermissionDenied.default_detail}, status=PermissionDenied.status_code)
class KeycloakUserManagement(UserManagement): def __init__(self, ex, parameters=None): from keycloak import KeycloakOpenID if parameters is None: parameters = {} self.ex = ex self.server_url = parameters["server_url"] self.client_id = parameters["client_id"] self.realm_name = parameters["realm_name"] self.client_secret_key = parameters["client_secret_key"] self.keycloak_manager = KeycloakOpenID( server_url=self.server_url, client_id=self.client_id, realm_name=self.realm_name, client_secret_key=self.client_secret_key) UserManagement.__init__(self, ex) def do_login(self, user, password): """ Logs in a user and returns a session id Parameters ------------ user Username password Password Returns ------------ session_id Session ID """ try: token = self.keycloak_manager.token(user, password) return token['access_token'] except: # traceback.print_exc() pass return None def check_session_validity(self, session_id): """ Checks the validity of a session Parameters ------------ session_id Session ID Returns ------------ boolean Boolean value """ validity = False try: if not (str(session_id) == "null"): userinfo = self.keycloak_manager.userinfo(session_id) if type(userinfo["preferred_username"]) is str: if userinfo["preferred_username"]: validity = True except: # traceback.print_exc() pass return validity def get_user_from_session(self, session_id): """ Gets the user from the session Parameters ------------ session_id Session ID Returns ------------ user User ID """ user = None try: if not (str(session_id) == "null"): userinfo = self.keycloak_manager.userinfo(session_id) if type(userinfo["preferred_username"]) is str: if userinfo["preferred_username"]: user = userinfo["preferred_username"] except: # traceback.print_exc() pass return user def clean_expired_sessions(self): """ Cleans the expired sessions in IAM """ pass def get_all_sessions(self): """ Gets all sessions from the users database Returns ----------- sessions List of sessions """ return None def get_all_users(self): """ Possibly get all the users from the users database Returns ------------- users List of users """ return []
class NDMWS: ''' Main class to talk to NDM Web Services. NDM public web services are at endpoints: - /api/mprc: MAVProxy Remote Console services (add, remove, list and update data) - /api/rmp: Reactive Mission Planner services (send or retrieve subplan, get GPS pos) In order to use these service, an authentication bearer is required that should be sent along with the request to any service. The NDMWS library helps with this authentication and provides several shortcuts to common sequences of service requests. A tipical use of the library could be: 1. Connect to Keycloak (retrieve the authentication bearer) 2. Create a custom subplan 3. Send the subplan to the RMP Other tipical (shorter) use could be: 1. Connect to Keycloak (retrieve the authentication bearer) 2. Trigger a predefined alarm (with its mapped subplan) In this last case, the alarm is only a label identifying a predefined mapping that we want to call use. This requires an association between the alarm and a subplan that should be defined in the configuration file in advance. The alarm is then sent to the vMPA and the mapped subplan is sent to the vDFC for execution. ''' def __init__(self, dfcaddr=None, droneid=None, mpaaddr=None, inifile='ndmws.ini', debug=False): ''' Creates an instance of the helper to call NDM Web Services. This is the first object to instantiate and the one to start WS interaction. You can specify `dfcaddr`, `mpaaddr` and a `droneid` or you can leave it blank. In this case, you an alternativelly inform the `inifile` name or leave the defaults. Debug is `False` by default, so you'll have to set `debug=True` to see config variables, i.e. ''' global DEBUG DEBUG = debug config.read(inifile) if dfcaddr == None: _('Using config: %s' % inifile) self.dfcaddr = config.get('dfc', 'hostport') else: self.dfcaddr = dfcaddr if mpaaddr == None: self.mpaaddr = config.get('mpa', 'hostport') _('Using mpaaddr: %s' % self.mpaaddr) else: self.mpaaddr = mpaaddr if droneid == None: self.droneid = config.get('dfc', 'droneid') _('Using droneid: %s' % self.droneid) else: self.droneid = droneid self.logger = logging.getLogger(__name__) # create console handler with a higher log level ch = logging.StreamHandler() ch.setLevel(logging.INFO) # create formatter and add it to the handlers formatter = logging.Formatter( "%(asctime)s.%(msecs)03d[%(levelname)-8s]:%(created).3f %(message)s", datefmt="%Y-%m-%d %H:%M:%S") ch.setFormatter(formatter) # add the handlers to logger if (self.logger.hasHandlers()): self.logger.handlers.clear() self.logger.addHandler(ch) self.logger.propagate = False self.authenticate() self.last_t_subplan = 0 # self.relay_bcp_client = RelayClient( # password=PASSWORD, # keyfile=KEYFILE, # identity=IDENTITY, # can be set afterwards by calling `client.set_identity(identity)` # tx_relay_address=TX_RELAY_ADDRESS, # meta_identity_manager_address=META_IDENTITY_MANAGER_ADDRESS, # entity_data_manager_address=ENTITY_DATA_MANAGER_ADDRESS, # relay_server_address=RELAY_ENDPOINT,) # self.vmme_producer = None # self.initialized_vmme = False def authenticate(self, hostport=None, username=None, password=None): ''' Authentication with Keycloak is required before any API interaction. Realm is hardcoded to 'ndmws' and client 'ndmws-client', so no other configuration is required. Note that the communication is always encrypted so no plain text is on the wire, but you should protect your configuration file from unathorized access (i.e. don't ever commit your ndmws.ini file in your repo). ''' if hostport == None or username == None or password == None: hostport = config.get('auth', 'hostport') _('Using auth hostport: %s' % hostport) username = config.get('auth', 'username') _('Using auth username: %s' % username) password = config.get('auth', 'password') _('Using auth password: %s' % password) _('Using auth url: %s' % (AUTHURL % hostport)) self.kc = KeycloakOpenID(server_url=AUTHURL % hostport, client_id='ndmws-client', realm_name='ndmws') self.token = self.kc.token(username, password) self.logger.info(self.token) def userinfo(self): ''' Get keycloak user info from the identity server. This is only required if you want to be sure that the user you are authenticating with is the one allowed to interact with the web services, also no estrictly neccessary. ''' return self.kc.userinfo(self.token['access_token']) def getpos(self, ts, th): ''' Get the GPS position of the flying drone when time = `ts`. While the drone (in config) is flying, every instant can be resolved to a known GPS position. This method retrieves the GPS position from the done `traces` before the drone lands. The opposite is not true, since the drone might (and usually does) pass twice or more to the same GPS position. ''' auth = self.token['access_token'] trace_url = TRACEURL % (self.dfcaddr, self.droneid, ts, th) r = get(trace_url, headers={'Authorization': 'Bearer %s' % auth}) self.logger.info("RESPONSE GETPOS: {}".format(r.text)) if r.status_code == 200: j = loads(r.text) return {'time': j['time'], 'pos': j['pos']} else: return {'code': r.status_code, 'msg': r.json()['msg']} def sendplan(self, data): ''' Send a subplan to the vDFC for a subplan change. With this method you can arbitrarily send a hand-made subplan (JSON) or a plan constructed using the `Subplan` fluent language builder. The plan will be executed only if the drone is not currently executing a subplan. If the drone is yet executing a subplan, an 409 error will be issued, but you can catch and ignore it as you wish, since no exception is raised at this moment. ''' auth = self.token['access_token'] r = put(SUBPLANURL % (self.dfcaddr, self.droneid), json=loads(data) if type(data) == str else data, headers={'Authorization': 'Bearer %s' % auth}) self.logger.info('SUBPLAN RESPONSE: {}'.format(r.text)) if r.status_code == 200: return r.text else: return {'code': r.status_code, 'msg': r.json()['msg']} def sendalarm(self, src, obj, ts): ''' Send an alarm to the vMPA for notification. Use this method to send a notification to the vMPA party. This notification could be sent in parallel to a subplan change (i.e. senplan) in the vDFC, so that both parties are notified of the alarm at the same time or sent by itself when an uploaded video is being processed. The 'src' param should be self.droneid if the video source comes from a drone live video or the label id (user supplied when a video is uploaded. 'object' identification and actual time 'ts' should also be passed as a way to enrich the alert message. ''' auth = self.token['access_token'] r = put(ALARMURL % (self.mpaaddr, src, obj, ts), headers={'Authorization': 'Bearer %s' % auth}) self.logger.info("Response ALARM:{}".format(r.text)) if r.status_code == 200: return r.text else: return {'code': r.status_code, 'msg': r.json()['msg']} def triggeralarm(self, alarm, t, subplan_time_space=60, send_subplan=False, threshold=GPS_POS_THRESHOLD): ''' Trigger an alarm and send a predefined subplan to the RMP (Reactive Mission Planner). Predefined subplans could be configured in the configuration file easily following this structure: [alarmmap] ALARM = SP_SUBPLAN_NAME By adding a mapping between an alarm name and a suplan name, the library knows which subplan should be loaded when an alarm is triggered. [ALARM] reason = reason_text object = object_text A new section should be added for every new alarm, specifying two keys, `reason` and `object` that will be substituted into every subplan mapped to this alarm. [subplans] SP_SUBPLAN_NAME = { subplan: [ ... ] } A new key should be added to the `subplans` section to write the JSON corresponding to the subplan. Of course, the subplan object can (and should) include substitution variables that need to be escaped (use a double `%`) to avoid early template subtitution. Allowed template variables are as follows: - clientid - reason - obj - lat - lon - alt ''' try: resp = self.getpos(t, threshold) if 'code' in resp: # self.logger.info('Exception of drone not flying') raise Exception('%d: %s' % (resp['code'], resp['msg'])) else: _('Event: %s' % alarm) sp = config.get('alarmmap', alarm) _('Subplan name: %s' % sp) if sp == None: raise Exception('ERROR: alarm `%s` has no mapped subplan' % alarm) subplan = config.get('subplans', sp) _('Subplan: %s' % subplan) reason = config.get(alarm, 'reason') obj = config.get(alarm, 'object') _('Sending alert of object %s at time %d' % (obj, t)) self.sendalarm(self.droneid, obj, t) if t > (self.last_t_subplan + subplan_time_space * 1000) and send_subplan: clientid = config.get('client', 'clientid') params = resp['pos'] params.update({ 'clientid': clientid, 'reason': reason, 'obj': obj }) _('Subplan params: %s' % params.__str__()) self.logger.info(('Subplan params: %s' % params.__str__())) subplan = subplan % params _('Sending subplan: %s' % subplan) # vBCP client # params["ts"] = t # self.send_bcp_data(params) # vMME client # self.send_mme_data(params) # self.last_t_subplan = t self.logger.info("sending subplan") return self.sendplan(subplan) else: # if (int((t-self.last_t_subplan)*0.001)) % 10 == 0: # self.logger.info('No subplans allowed. Last one sent {}(s) ago'.format(int((t-self.last_t_subplan)*0.001))) return {'code': 200, 'msg': 'No subplans allowed'} except Exception: pass def send_bcp_data(self, data): payload = dumps(data) # Relay the payload as a signed message to the Relay Server. The message will be forwarded to the vMCM. self.logger.info( 'Relaying signed payload to the server: {}'.format(payload)) # status = self.relay_bcp_client.relay_signed_message(payload) # self.logger.info('Got status code : {}'.format(status)) tx_hash = self.relay_bcp_client.register_mpa_data(payload) self.logger.info('Got transaction hash : {}'.format(tx_hash)) self.logger.info("data has been sent to vBCP") # def init_mme(self, data): # device_data = self.generate_mme_data(data) # send_init_msg_influx(device_data) def generate_mme_data(self, data): topic = generate_mqtt_topics() device_data = { "device_id": "DEVICE_ID_VMPA", "device_name": "DEVICE_NAME_VMPA", "device_ip": self.droneid, "lat": data['lat'], "lon": data['lon'], "prev_mme": "none", "sender": "device", "device_topic": topic, # data["topic"] if "topic" in data.keys() else data["reason"], "entity_type": "drone" } return device_data def send_mme_data(self, data): db_path = "vmme_client/device.db" device_data = self.generate_mme_data(data) self.write_mme_data(db_path, device_data) self.logger.info("Data has been sent to vMME") def write_mme_data(self, db_path, device_data): self.logger.info("On write_mme_data") self.logger.info(self.initialized_vmme) if self.initialized_vmme == False: self.logger.info("TO INITIALIZE VMME") initialize_vmme(db_path, device_data) # send_init_msg_influx(device_data) # FIRST_BROKER = select(db_path, device_data["device_id"]) # # if DEMO: # # try: # # base = BaseClient(password=password, # # keyfile="vmme_client/keyfile.json") # # base.create_keyfile() # # vmme_wallet_addr = base._fetch_signer_address() # # identity_hash_response = create_identity(vmme_wallet_addr) # # identity_hash = identity_hash_response.json() # # valid_identity(identity_hash["tx_hash"].strip(), vmme_wallet_addr, device_data["entity_type"]) # # self.logger.info("The device registration to the vAAA was successful: \n") # # except Exception as e: # # self.logger.info(e) # insert_ip(db_path, FIRST_BROKER) # insert_device_data(db_path, device_data) self.vmme_producer = Producer() self.initialized_vmme = True self.logger.info("Initialized vMME") if self.vmme_producer: self.vmme_producer.operate(device_data["device_id"]) self.logger.info("Out of write mme data")
class AuthentificationMiddleware: def __init__(self, get_response): self.get_response = get_response # One-time configuration and initialization. self.config = settings.KEYCLOAK_IAM_CLIENT_CONFIG try: self.server_url = self.config['KEYCLOAK_SERVER_URL'] self.client_id = self.config['KEYCLOAK_CLIENT_ID'] self.realm = self.config['KEYCLOAK_REALM'] except KeyError: raise Exception( "KEYCLOAK_SERVER_URL, KEYCLOAK_CLIENT_ID or KEYCLOAK_REALM not found.") self.client_secret_key = self.config.get( 'KEYCLOAK_CLIENT_SECRET_KEY', None) self.client_public_key = self.config.get( 'KEYCLOAK_CLIENT_PUBLIC_KEY', None) self.default_access = self.config.get( 'KEYCLOAK_DEFAULT_ACCESS', "DENY") self.method_validate_token = self.config.get( 'KEYCLOAK_METHOD_VALIDATE_TOKEN', "INTROSPECT") self.keycloak_authorization_config = self.config.get( 'KEYCLOAK_AUTHORIZATION_CONFIG', None) self.keycloak = KeycloakOpenID(server_url=self.server_url, client_id=self.client_id, realm_name=self.realm, client_secret_key=self.client_secret_key) @property def keycloak(self): return self._keycloak @keycloak.setter def keycloak(self, value): self._keycloak = value @property def config(self): return self._config @config.setter def config(self, value): self._config = value @property def server_url(self): return self._server_url @server_url.setter def server_url(self, value): self._server_url = value @property def client_id(self): return self._client_id @client_id.setter def client_id(self, value): self._client_id = value @property def client_secret_key(self): return self._client_secret_key @client_secret_key.setter def client_secret_key(self, value): self._client_secret_key = value @property def client_public_key(self): return self._client_public_key @client_public_key.setter def client_public_key(self, value): self._client_public_key = value @property def realm(self): return self._realm @realm.setter def realm(self, value): self._realm = value @property def keycloak_authorization_config(self): return self._keycloak_authorization_config @keycloak_authorization_config.setter def keycloak_authorization_config(self, value): self._keycloak_authorization_config = value @property def method_validate_token(self): return self._method_validate_token @method_validate_token.setter def method_validate_token(self, value): self._method_validate_token = value def __call__(self, request): print("queryString", request.META.get('QUERY_STRING', '')) # Code to be executed for each request before # the view (and later middleware) are called. response = self.get_response(request) # Code to be executed for each request/response after # the view is called. return response def process_view(self, request, view_func, view_args, view_kwargs): if hasattr(settings, 'KEYCLOAK_BEARER_AUTHENTICATION_EXEMPT_PATHS'): path = request.path_info.lstrip('/') if any(re.match(m, path) for m in settings.KEYCLOAK_BEARER_AUTHENTICATION_EXEMPT_PATHS): logger.debug('** exclude path found, skipping') return None if 'HTTP_AUTHORIZATION' not in request.META: token_request = request.META.get('QUERY_STRING' , "") print('token_request' , token_request) print("init =====" , request.GET , request.META) initToken = token_request.split('init=')[-1].split("&")[0] request_type = request.META.get('CONTENT_TYPE' , '') print('text/html' == request_type , 'text/plain' == request_type) if not initToken and not 'text/html' == request_type and not 'text/plain' == request_type: return JsonResponse({"detail": NotAuthenticated.default_detail}, status=NotAuthenticated.status_code) else: token = initToken else: auth_header = request.META.get('HTTP_AUTHORIZATION').split() token = auth_header[1] if len(auth_header) == 2 else auth_header[0] try: user = self.keycloak.userinfo(token) request.authUser = user except KeycloakInvalidTokenError: return JsonResponse({"detail": AuthenticationFailed.default_detail, "code": settings.CUSTOM_ERRORS_TEXT['AUTHENTIFICATION_FAILLED']}, status=AuthenticationFailed.status_code) except KeycloakAuthenticationError as e: return JsonResponse({"detail": "Token Expiré veuillez refresh", "code": settings.CUSTOM_ERRORS_TEXT['REFRESH_TOKEN']}, status=AuthenticationFailed.status_code) return None