def token_endpoint(self, request="", authn=None, dtype='urlencoded', **kwargs): try: req = AccessTokenRequest().deserialize(request, dtype) client_id = self.client_authn(self, req, authn) except FailedAuthentication as err: logger.error(err) self.events.store(EV_EXCEPTION, "Failed to verify client due to: {}".format(err)) return error_response(error="invalid_client", descr=err.args[0]) except Exception as err: logger.error(err) self.events.store(EV_EXCEPTION, "Failed to verify client due to: %s" % err) return error_response(error="invalid_client", descr="Failed to verify client: {}".format(err)) try: self._update_client_keys(client_id) except TestError: logger.error('No change in client keys') return error_response(error="incorrect_behavior", descr="No change in client keys") _response = provider.Provider.token_endpoint(self, request, authn, dtype, **kwargs) return _response
def providerinfo_endpoint(self, handle="", **kwargs): _log_info = logger.info _log_info("@providerinfo_endpoint") try: _response = self.create_providerinfo() msg = "provider_info_response: {}" _log_info(msg.format(sanitize(_response.to_dict()))) if self.events: self.events.store("Protocol response", _response) headers = [("Cache-Control", "no-store")] if handle: (key, timestamp) = handle if key.startswith(STR) and key.endswith(STR): cookie = self.cookie_func( key, self.cookie_name, "pinfo", self.sso_ttl ) headers.append(cookie) resp = Response( _response.to_json(), content="application/json", headers=headers ) except Exception: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = error_response("service_error", message) return resp
def providerinfo_endpoint(self, handle="", **kwargs): """ The Provider info endpoint. A request for provider info should be handled by this method. It will work as well for requests from federation aware RPs as for non-federation aware RPs. :param handle: (key, timestamp) tuple used at cookie construction :param kwargs: Extra key word arguments. :return: Provider Info response """ logger.info("@providerinfo_endpoint") try: _response = self.create_fed_providerinfo() msg = "provider_info_response: {}" logger.info(msg.format(sanitize(_response.to_dict()))) if self.events: self.events.store('Protocol response', _response) headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")] if handle: (key, timestamp) = handle if key.startswith(STR) and key.endswith(STR): cookie = self.cookie_func(key, self.cookie_name, "pinfo", self.sso_ttl) headers.append(cookie) resp = Response(_response.to_json(), content="application/json", headers=headers) except Exception: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = error_response('service_error', message) return resp
def password_grant_type(self, areq): """ Token authorization using Resource owner password credentials. RFC6749 section 4.3 """ # This is not implemented here, please see oic.extension.provider. return error_response("unsupported_grant_type", descr="Unsupported grant_type")
def refresh_token_grant_type(self, areq): """ Token refresh. RFC6749 section 6 """ # This is not implemented here, please see oic.extension.provider. return error_response("unsupported_grant_type", descr="Unsupported grant_type")
def client_credentials_grant_type(self, areq): """ Token authorization using client credentials. RFC6749 section 4.4 """ # This is not implemented here, please see oic.extension.provider. return error_response('unsupported_grant_type', descr='Unsupported grant_type')
def userinfo_endpoint(self, request, **kwargs): access_token = self._parse_access_token(request) shr = SignedHttpRequest(self._get_client_public_key(access_token)) http_signature = self._parse_signature(request) try: shr.verify( http_signature, method=request["method"], host=request["host"], path=request["path"], query_params=request["query"], headers=request["headers"], body=request["body"], strict_query_param_verification=True, strict_headers_verification=False, ) except ValidationError: return error_response("access_denied", descr="Could not verify proof of " "possession") return self._do_user_info(self.access_tokens[access_token], **kwargs)
def _complete_authz(self, user, areq, sid, **kwargs): _log_debug = logger.debug _log_debug("- in authenticated() -") # Do the authorization try: permission = self.authz(user, client_id=areq['client_id']) self.sdb.update(sid, "permission", permission) except Exception: raise _log_debug("response type: %s" % areq["response_type"]) if self.sdb.is_revoked(sid): return error_response("access_denied", descr="Token is revoked") try: info = self.create_authn_response(areq, sid) except UnSupported as err: return error_response(*err.args) if isinstance(info, Response): return info else: aresp, fragment_enc = info try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return BadRequest("%s" % err) # Must not use HTTP unless implicit grant type and native application info = self.aresp_check(aresp, areq) if isinstance(info, Response): return info headers = [] try: _kaka = kwargs["cookie"] except KeyError: pass else: if _kaka: if isinstance(_kaka, dict): for name, val in _kaka.items(): _c = SimpleCookie() _c[name] = val _x = _c.output() if PY2: _x = str(_x) headers.append(tuple(_x.split(": ", 1))) else: _c = SimpleCookie() _c.load(_kaka) for x in _c.output().split('\r\n'): if PY2: x = str(x) headers.append(tuple(x.split(": ", 1))) if self.cookie_name not in _kaka: # Don't overwrite header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl) if header: headers.append(header) else: header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl) if header: headers.append(header) # Now about the response_mode. Should not be set if it's obvious # from the response_type. Knows about 'query', 'fragment' and # 'form_post'. if "response_mode" in areq: try: resp = self.response_mode(areq, fragment_enc, aresp=aresp, redirect_uri=redirect_uri, headers=headers) except InvalidRequest as err: return error_response("invalid_request", str(err)) else: if resp is not None: return resp return aresp, headers, redirect_uri, fragment_enc
def auth_init(self, request, request_class=AuthorizationRequest): """ :param request: The AuthorizationRequest :return: """ logger.debug("Request: '%s'" % sanitize(request)) # Same serialization used for GET and POST try: areq = self.server.parse_authorization_request( request=request_class, query=request) except (MissingRequiredValue, MissingRequiredAttribute, AuthzError) as err: logger.debug("%s" % err) areq = request_class() areq.lax = True if isinstance(request, dict): areq.from_dict(request) else: areq.deserialize(request, "urlencoded") try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError, UnknownClient) as err: return error_response("invalid_request", "%s" % err) try: _rtype = areq["response_type"] except KeyError: _rtype = ["code"] try: _state = areq["state"] except KeyError: _state = '' return redirect_authz_error("invalid_request", redirect_uri, "%s" % err, _state, _rtype) except KeyError: areq = request_class().deserialize(request, "urlencoded") # verify the redirect_uri try: self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return error_response("invalid_request", "%s" % err) except Exception as err: message = traceback.format_exception(*sys.exc_info()) logger.error(message) logger.debug("Bad request: %s (%s)" % (err, err.__class__.__name__)) err = ErrorResponse(error='invalid_request', error_description=str(err)) return BadRequest(err.to_json(), content='application/json') if not areq: logger.debug("No AuthzRequest") return error_response("invalid_request", "Can not parse AuthzRequest") areq = self.filter_request(areq) if self.events: self.events.store('Protocol request', areq) try: _cinfo = self.cdb[areq['client_id']] except KeyError: logger.error( 'Client ID ({}) not in client database'.format( areq['client_id'])) return error_response('unauthorized_client', 'unknown client') else: try: _registered = [set(rt.split(' ')) for rt in _cinfo['response_types']] except KeyError: # If no response_type is registered by the client then we'll # code which it the default according to the OIDC spec. _registered = [{'code'}] _wanted = set(areq["response_type"]) if _wanted not in _registered: return error_response("invalid_request", "Trying to use unregistered response_typ") logger.debug("AuthzRequest: %s" % (sanitize(areq.to_dict()),)) try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError, UnknownClient) as err: return error_response("invalid_request", "{}:{}".format(err.__class__.__name__, err)) try: keyjar = self.keyjar except AttributeError: keyjar = "" try: # verify that the request message is correct areq.verify(keyjar=keyjar, opponent_id=areq["client_id"]) except (MissingRequiredAttribute, ValueError, MissingRequiredValue) as err: return redirect_authz_error("invalid_request", redirect_uri, "%s" % err) return {"areq": areq, "redirect_uri": redirect_uri}
def authorization_endpoint(self, request="", cookie=None, **kwargs): if isinstance(request, dict): _req = request else: _req = {} for key, val in parse_qs(request).items(): if len(val) == 1: _req[key] = val[0] else: _req[key] = val # self.events.store(EV_REQUEST, _req) try: _scope = _req["scope"] except KeyError: return error( error="incorrect_behavior", descr="No scope parameter" ) else: # verify that openid is among the scopes _scopes = _scope.split(" ") if "openid" not in _scopes: return error( error="incorrect_behavior", descr="Scope does not contain 'openid'" ) client_id = _req["client_id"] try: f = response_type_cmp(self.capabilities['response_types_supported'], _req['response_type']) except KeyError: pass else: if f is False: self.events.store( EV_FAULT, 'Wrong response type: {}'.format(_req['response_type'])) return error_response(error="incorrect_behavior", descr="Not supported response_type") _rtypes = _req['response_type'].split(' ') if 'id_token' in _rtypes: try: self._update_client_keys(client_id) except TestError: return error(error="incorrect_behavior", descr="No change in client keys") if isinstance(request, dict): request = urlencode(request) _response = provider.Provider.authorization_endpoint(self, request, cookie, **kwargs) if "rotenc" in self.behavior_type: # Rollover encryption keys rsa_key = RSAKey(kid="rotated_rsa_{}".format(time.time()), use="enc").load_key(RSA.generate(2048)) ec_key = ECKey(kid="rotated_ec_{}".format(time.time()), use="enc").load_key(P256) keys = [rsa_key.serialize(private=True), ec_key.serialize(private=True)] new_keys = {"keys": keys} self.events.store("New encryption keys", new_keys) self.do_key_rollover(new_keys, "%d") self.events.store("Rotated encryption keys", '') logger.info( 'Rotated OP enc keys, new set: {}'.format( key_summary(self.keyjar, ''))) # This is just for logging purposes try: _resp = self.server.http_request(_req["request_uri"]) except KeyError: pass except requests.ConnectionError as err: self.events.store(EV_EXCEPTION, err) err = unwrap_exception(err) return error_response(error="server_error", descr=err) else: if _resp.status_code == 200: self.events.store(EV_REQUEST, "Request from request_uri: {}".format( _resp.text)) return _response
def _complete_authz(self, user, areq, sid, **kwargs): _log_debug = logger.debug _log_debug("- in authenticated() -") # Do the authorization try: permission = self.authz(user, client_id=areq['client_id']) self.sdb.update(sid, "permission", permission) except Exception: raise _log_debug("response type: %s" % areq["response_type"]) if self.sdb.is_revoked(sid): return error_response("access_denied", descr="Token is revoked") try: info = self.create_authn_response(areq, sid) except UnSupported as err: return error_response(*err.args) if isinstance(info, Response): return info else: aresp, fragment_enc = info try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return BadRequest("%s" % err) # Must not use HTTP unless implicit grant type and native application info = self.aresp_check(aresp, areq) if isinstance(info, Response): return info headers = [] try: _kaka = kwargs["cookie"] except KeyError: _kaka = None c_val = "{}{}{}".format(user, DELIM, areq['client_id']) cookie_header = None if _kaka is not None: if self.cookie_name not in _kaka: # Don't overwrite cookie_header = self.cookie_func( c_val, typ="sso", cookie_name=self.sso_cookie_name, ttl=self.sso_ttl) else: cookie_header = self.cookie_func(c_val, typ="sso", cookie_name=self.sso_cookie_name, ttl=self.sso_ttl) if cookie_header is not None: headers.append(cookie_header) # Now about the response_mode. Should not be set if it's obvious # from the response_type. Knows about 'query', 'fragment' and # 'form_post'. if "response_mode" in areq: try: resp = self.response_mode(areq, fragment_enc, aresp=aresp, redirect_uri=redirect_uri, headers=headers) except InvalidRequest as err: return error_response("invalid_request", str(err)) else: if resp is not None: return resp return aresp, headers, redirect_uri, fragment_enc
def registration_endpoint(self, request, authn=None, **kwargs): try: reg_req = RegistrationRequest().deserialize(request, "json") except ValueError: reg_req = RegistrationRequest().deserialize(request) self.events.store(EV_PROTOCOL_REQUEST, reg_req) try: response_type_cmp(kwargs['test_cnf']['response_type'], reg_req['response_types']) except KeyError: pass try: provider.Provider.verify_redirect_uris(reg_req) except InvalidRedirectURIError as err: return error_response(error="invalid_configuration_parameter", descr="Invalid redirect_uri: {}".format(err)) if "initiate_login_uri" in self.behavior_type: # ?? if not "initiate_login_uri" in reg_req: return error_response( error="invalid_configuration_parameter", descr="No \"initiate_login_uri\" endpoint found in the " "Client Registration Request\"") # Do initial verification that all endpoints from the client uses # https for endp in ["jwks_uri", "initiate_login_uri"]: try: uris = reg_req[endp] except KeyError: continue if not isinstance(uris, list): uris = [uris] for uri in uris: if not uri.startswith("https://"): return error_response( error="invalid_configuration_parameter", descr="Non-HTTPS endpoint in '{}'".format(endp)) if not "contacts" in reg_req: return error_response( error="invalid_configuration_parameter", descr="No \"contacts\" claim provided in registration request." ) elif not "@" in reg_req["contacts"][0]: return error_response( error="invalid_configuration_parameter", descr="First address in \"contacts\" value in registration " "request is not a valid e-mail address.") _response = provider.Provider.registration_endpoint( self, request, authn, **kwargs) self.events.store(EV_HTTP_RESPONSE, _response) self.init_keys = [] if "jwks_uri" in reg_req: if _response.status_code == 200: # find the client id req_resp = RegistrationResponse().from_json(_response.message) for kb in self.keyjar[req_resp["client_id"]]: if kb.imp_jwks: self.events.store("Client JWKS", kb.imp_jwks) return _response
def registration_endpoint(self, request, authn=None, **kwargs): """ Registration endpoint. This is where a registration request should be handled. :param request: The request, either as a dictionary or as a JSON document :param authn: Authentication information :param kwargs: Extra key work arguments. :return: A request response or an error response. """ logger.debug("@registration_endpoint: <<{}>>".format( sanitize(request))) if isinstance(request, dict): request = ClientMetadataStatement(**request) else: try: request = ClientMetadataStatement().deserialize( request, "json") except ValueError: request = ClientMetadataStatement().deserialize(request) if not self.is_federation_request(request): return provider.Provider.registration_endpoint(self, request.to_json(), authn=None, **kwargs) try: request.verify() except Exception as err: return error_response('Invalid request') logger.info("registration_request:{}".format( sanitize(request.to_dict()))) les = self.federation_entity.get_metadata_statement( request, 'registration') if les: ms = self.federation_entity.pick_by_priority(les) self.federation = ms.fo else: # Nothing I can use return error_response( error='invalid_request', descr='No signed metadata statement I could use') _pc = ms.protected_claims() if _pc: request = RegistrationRequest(**_pc) else: request = RegistrationRequest( **ms.unprotected_and_protected_claims()) result = self.client_registration_setup(request) if 'signed_jwks_uri' in _pc: _kb = KeyBundle(source=_pc['signed_jwks_uri'], verify_keys=ms.signing_keys, verify_ssl=False) _kb.do_remote() replace_jwks_key_bundle(self.keyjar, result['client_id'], _kb) result['signed_jwks_uri'] = _pc['signed_jwks_uri'] if isinstance(result, Response): return result # TODO This is where the OP should sign the response if ms.fo: _fo = ms.fo _sig = self._signer() if _sig: sms = _sig.create_signed_metadata_statement(result, 'response', [_fo], single=True) else: raise SigningServiceError('No Signer') self.federation_entity.extend_with_ms(result, {_fo: sms}) return Created(result.to_json(), content="application/json", headers=[("Cache-Control", "no-store")])
def _complete_authz(self, user, areq, sid, **kwargs): _log_debug = logger.debug _log_debug("- in authenticated() -") # Do the authorization try: permission = self.authz(user, client_id=areq['client_id']) self.sdb.update(sid, "permission", permission) except Exception: raise _log_debug("response type: %s" % areq["response_type"]) if self.sdb.is_revoked(sid): return error_response("access_denied", descr="Token is revoked") try: info = self.create_authn_response(areq, sid) except UnSupported as err: return error_response(*err.args) if isinstance(info, Response): return info else: aresp, fragment_enc = info try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return BadRequest("%s" % err) # Must not use HTTP unless implicit grant type and native application info = self.aresp_check(aresp, areq) if isinstance(info, Response): return info headers = [] try: _kaka = kwargs["cookie"] except KeyError: _kaka = None c_val = "{}{}{}".format(user, DELIM, areq['client_id']) cookie_header = None if _kaka is not None: if self.cookie_name not in _kaka: # Don't overwrite cookie_header = self.cookie_func(c_val, typ="sso", cookie_name=self.sso_cookie_name, ttl=self.sso_ttl) else: cookie_header = self.cookie_func(c_val, typ="sso", cookie_name=self.sso_cookie_name, ttl=self.sso_ttl) if cookie_header is not None: headers.append(cookie_header) # Now about the response_mode. Should not be set if it's obvious # from the response_type. Knows about 'query', 'fragment' and # 'form_post'. if "response_mode" in areq: try: resp = self.response_mode(areq, fragment_enc, aresp=aresp, redirect_uri=redirect_uri, headers=headers) except InvalidRequest as err: return error_response("invalid_request", str(err)) else: if resp is not None: return resp return aresp, headers, redirect_uri, fragment_enc
def authorization_endpoint(self, request="", cookie=None, **kwargs): if isinstance(request, dict): _req = request else: _req = {} for key, val in parse_qs(request).items(): if len(val) == 1: _req[key] = val[0] else: _req[key] = val # self.events.store(EV_REQUEST, _req) try: _scope = _req["scope"] except KeyError: return error_response( error="incorrect_behavior", descr="No scope parameter" ) else: # verify that openid is among the scopes _scopes = _scope.split(" ") if "openid" not in _scopes: return error_response( error="incorrect_behavior", descr="Scope does not contain 'openid'" ) client_id = _req["client_id"] try: f = response_type_cmp(self.capabilities['response_types_supported'], _req['response_type']) except KeyError: pass else: if f is False: self.events.store( EV_FAULT, 'Wrong response type: {}'.format(_req['response_type'])) return error_response(error="incorrect_behavior", descr="Not supported response_type") _rtypes = _req['response_type'].split(' ') if 'id_token' in _rtypes: try: self._update_client_keys(client_id) except TestError: return error_response(error="incorrect_behavior", descr="No change in client keys") if isinstance(request, dict): request = urlencode(request) if "max_age" in _req and _req["max_age"] == "0" and "prompt" in _req and _req["prompt"] == "none": aresp = { "error": "login_required", } if "state" in _req: aresp['state'] = _req["state"] return self.response_mode(_req, False, aresp=aresp, redirect_uri=_req['redirect_uri'], headers={}) else: _response = provider.Provider.authorization_endpoint(self, request, cookie, **kwargs) if "rotenc" in self.behavior_type: # Rollover encryption keys rsa_key = RSAKey(kid="rotated_rsa_{}".format(time.time()), use="enc").load_key(RSA.generate(2048)) ec_key = ECKey(kid="rotated_ec_{}".format(time.time()), use="enc").load_key(P256) keys = [rsa_key.serialize(private=True), ec_key.serialize(private=True)] new_keys = {"keys": keys} self.events.store("New encryption keys", new_keys) self.do_key_rollover(new_keys, "%d") self.events.store("Rotated encryption keys", '') logger.info( 'Rotated OP enc keys, new set: {}'.format( key_summary(self.keyjar, ''))) # This is just for logging purposes try: _resp = self.server.http_request(_req["request_uri"]) except KeyError: pass except requests.ConnectionError as err: self.events.store(EV_EXCEPTION, err) err = unwrap_exception(err) return error_response(error="server_error", descr=err) else: if _resp.status_code == 200: self.events.store(EV_REQUEST, "Request from request_uri: {}".format( _resp.text)) return _response
def registration_endpoint(self, request, authn=None, **kwargs): try: reg_req = RegistrationRequest().deserialize(request, "json") except ValueError: reg_req = RegistrationRequest().deserialize(request) self.events.store(EV_PROTOCOL_REQUEST, reg_req) try: response_type_cmp(kwargs['test_cnf']['response_type'], reg_req['response_types']) except KeyError: pass try: provider.Provider.verify_redirect_uris(reg_req) except InvalidRedirectURIError as err: return error_response( error="invalid_configuration_parameter", descr="Invalid redirect_uri: {}".format(err)) if "initiate_login_uri" in self.behavior_type: if not "initiate_login_uri" in reg_req: return error_response( error="invalid_configuration_parameter", descr="No \"initiate_login_uri\" endpoint found in the Client Registration Request\"") # Do initial verification that all endpoints from the client uses # https for endp in ["jwks_uri", "initiate_login_uri"]: try: uris = reg_req[endp] except KeyError: continue if not isinstance(uris, list): uris = [uris] for uri in uris: if not uri.startswith("https://"): return error_response( error="invalid_configuration_parameter", descr="Non-HTTPS endpoint in '{}'".format(endp)) if not "contacts" in reg_req: return error_response( error="invalid_configuration_parameter", descr="No \"contacts\" claim provided in registration request.") elif not "@" in reg_req["contacts"][0]: return error_response( error="invalid_configuration_parameter", descr="First address in \"contacts\" value in registration request is not a valid e-mail address.") _response = provider.Provider.registration_endpoint(self, request, authn, **kwargs) self.events.store(EV_HTTP_RESPONSE, _response) self.init_keys = [] if "jwks_uri" in reg_req: if _response.status_code == 200: # find the client id req_resp = RegistrationResponse().from_json( _response.message) for kb in self.keyjar[req_resp["client_id"]]: if kb.imp_jwks: self.events.store("Client JWKS", kb.imp_jwks) return _response
def _complete_authz(self, user, areq, sid, **kwargs): _log_debug = logger.debug _log_debug("- in authenticated() -") # Do the authorization try: permission = self.authz(user, client_id=areq['client_id']) self.sdb.update(sid, "permission", permission) except Exception: raise _log_debug("response type: %s" % areq["response_type"]) if self.sdb.is_revoked(sid): return error_response("access_denied", descr="Token is revoked") try: info = self.create_authn_response(areq, sid) except UnSupported as err: return error_response(*err.args) if isinstance(info, Response): return info else: aresp, fragment_enc = info try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return BadRequest("%s" % err) # Must not use HTTP unless implicit grant type and native application info = self.aresp_check(aresp, areq) if isinstance(info, Response): return info headers = [] try: _kaka = kwargs["cookie"] except KeyError: pass else: if _kaka: if isinstance(_kaka, dict): for name, val in _kaka.items(): _c = SimpleCookie() _c[name] = val _x = _c.output() if PY2: _x = str(_x) headers.append(tuple(_x.split(": ", 1))) else: _c = SimpleCookie() _c.load(_kaka) for x in _c.output().split('\r\n'): if PY2: x = str(x) headers.append(tuple(x.split(": ", 1))) if self.cookie_name not in _kaka: # Don't overwrite header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl) if header: headers.append(header) else: header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl) if header: headers.append(header) # Now about the response_mode. Should not be set if it's obvious # from the response_type. Knows about 'query', 'fragment' and # 'form_post'. if "response_mode" in areq: try: resp = self.response_mode(areq, fragment_enc, aresp=aresp, redirect_uri=redirect_uri, headers=headers) except InvalidRequest as err: return error_response("invalid_request", str(err)) else: if resp is not None: return resp return aresp, headers, redirect_uri, fragment_enc
def auth_init(self, request, request_class=AuthorizationRequest): """ :param request: The AuthorizationRequest :return: """ logger.debug("Request: '%s'" % sanitize(request)) # Same serialization used for GET and POST try: areq = self.server.parse_authorization_request( request=request_class, query=request) except (MissingRequiredValue, MissingRequiredAttribute, AuthzError) as err: logger.debug("%s" % err) areq = request_class() areq.lax = True if isinstance(request, dict): areq.from_dict(request) else: areq.deserialize(request, "urlencoded") try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError, UnknownClient) as err: return error_response("invalid_request", "%s" % err) try: _rtype = areq["response_type"] except KeyError: _rtype = ["code"] try: _state = areq["state"] except KeyError: _state = '' return redirect_authz_error("invalid_request", redirect_uri, "%s" % err, _state, _rtype) except KeyError: areq = request_class().deserialize(request, "urlencoded") # verify the redirect_uri try: self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return error_response("invalid_request", "%s" % err) except Exception as err: message = traceback.format_exception(*sys.exc_info()) logger.error(message) logger.debug("Bad request: %s (%s)" % (err, err.__class__.__name__)) err = ErrorResponse(error='invalid_request', error_description=str(err)) return BadRequest(err.to_json(), content='application/json') if not areq: logger.debug("No AuthzRequest") return error_response("invalid_request", "Can not parse AuthzRequest") areq = self.filter_request(areq) if self.events: self.events.store('Protocol request', areq) try: _cinfo = self.cdb[areq['client_id']] except KeyError: logger.error( 'Client ID ({}) not in client database'.format( areq['client_id'])) return error_response('unauthorized_client', 'unknown client') else: try: _registered = [set(rt.split(' ')) for rt in _cinfo['response_types']] except KeyError: # If no response_type is registered by the client then we'll # code which it the default according to the OIDC spec. _registered = [{'code'}] _wanted = set(areq["response_type"]) if _wanted not in _registered: return error_response("invalid_request", "Trying to use unregistered response_typ") logger.debug("AuthzRequest: %s" % (sanitize(areq.to_dict()),)) try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError, UnknownClient) as err: return error_response("invalid_request", "{}:{}".format(err.__class__.__name__, err)) try: keyjar = self.keyjar except AttributeError: keyjar = "" try: # verify that the request message is correct areq.verify(keyjar=keyjar, opponent_id=areq["client_id"]) except (MissingRequiredAttribute, ValueError, MissingRequiredValue) as err: return redirect_authz_error("invalid_request", redirect_uri, "%s" % err) return {"areq": areq, "redirect_uri": redirect_uri}