def oauth2_start(self): if DEBUG_ROUTE: print("application:flow-register:oauth2:start", get_csrf_token(self.request)) if LOG_ROUTE: log.debug( "application:flow-register:oauth2:start %s", get_csrf_token(self.request), ) if DEBUG_USERID: print("application:account:oauth2:start", self.request.active_useraccount_id) if self.request.active_useraccount_id: return HTTPSeeOther("/application/account/home") authClient = OAuth2Session( OAUTH2__APP_KEY, redirect_uri=oauth2_utils.OAUTH2__URL_APP_FLOW_REGISTER_CALLBACK, ) # Redirect user to the App for authorization authorization_url, state = authClient.authorization_url( oauth2_utils.OAUTH2__URL_AUTHORITY_FLOWA_AUTHORIZATION) return HTTPSeeOther(authorization_url)
def token(self): """ this is called in two contexts: 1- a loggedin user is getting an access token for their client key/secret combo 2- a client app is exchanging an authorization code for an access token """ if DEBUG_ROUTE: print("authority:oauth2:token", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:oauth2:token %s", get_csrf_token(self.request)) try: user_id = self.request.active_useraccount_id if user_id is not None: credentials = dict(user_id=user_id) else: credentials = None oauth2Provider = new_oauth2Provider(self.request) rval = oauth2Provider.endopoint__token(credentials=credentials) return rval except HTTPException: raise except Exception as exc: # raise custom errors in production raise exc
def account_logout(self): if DEBUG_ROUTE: print("authority:account:logout", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:account:logout %s", get_csrf_token(self.request)) if self.request.active_useraccount_id: self.request.session.invalidate() return HTTPSeeOther("/authority/account/login-form")
def account_home(self): if DEBUG_ROUTE: print("authority:account:home", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:account:home %s", get_csrf_token(self.request)) if not self.request.active_useraccount_id: return HTTPSeeOther("/authority/account/login-form") return "authority|home|user=%s" % self.request.active_useraccount_id
def whoami(self): "This is used for writing tests" if DEBUG_ROUTE: print("whoami", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("whoami %s", get_csrf_token(self.request)) if DEBUG_USERID: print("whoami", self.request.active_useraccount_id) return "%s" % (self.request.active_useraccount_id or "")
def account_login_form(self): if DEBUG_ROUTE: print("authority:account:login-form", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:account:login-form %s", get_csrf_token(self.request)) if self.request.active_useraccount_id: return HTTPSeeOther("/authority/account/home") return "authority|login-form"
def revoke_token(self): """ revoke the User's token on the server """ if DEBUG_ROUTE: print("application:account:revoke-token", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("application:account:revoke-token %s", get_csrf_token(self.request)) if not self.request.active_useraccount_id: return HTTPSeeOther("/application/account/login-form") if self.request.active_useraccount_id != USERID_ACTIVE__APPLICATION: raise ValueError("not the expected user!") # what is our token? clientToken = ( self.request.dbSession.query(Developer_OAuth2Client_BearerToken). filter( Developer_OAuth2Client_BearerToken.useraccount_id == USERID_ACTIVE__APPLICATION, Developer_OAuth2Client_BearerToken.original_grant_type == "authorization_code", Developer_OAuth2Client_BearerToken.is_active == True, # noqa ).first()) if not clientToken: raise ValueError("no token for this user!") apiClient = oauth2_utils.CustomApiClientB( app_key=oauth2_model.OAUTH2__APP_KEY, app_secret=oauth2_model.OAUTH2__APP_SECRET, oauth_version=2, ) token_result = apiClient.revoke_access_token( token=clientToken.access_token) assert token_result is True clientToken.timestamp_revoked = self.request.datetime clientToken.is_active = False self.request.dbSession.flush() # just make sure it's marked as inactive on the server... _serverToken = ( self.request.dbSession.query(Developer_OAuth2Server_BearerToken). filter( Developer_OAuth2Server_BearerToken.useraccount_id == USERID_ACTIVE__AUTHORITY, Developer_OAuth2Server_BearerToken.original_grant_type == "authorization_code", Developer_OAuth2Server_BearerToken.is_active == False, # noqa Developer_OAuth2Server_BearerToken.access_token == clientToken.access_token, ).first()) assert _serverToken is not None return "revoked_token"
def account_login_submit(self): if DEBUG_ROUTE: print("authority:account:login-submit", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:account:login-submit %s", get_csrf_token(self.request)) self.request.session[ "active_useraccount_id"] = USERID_ACTIVE__AUTHORITY return HTTPSeeOther("/authority/account/home")
def oauth1_start(self): if DEBUG_ROUTE: print("application:flow-register:oauth1:start", get_csrf_token(self.request)) if LOG_ROUTE: log.debug( "application:flow-register:oauth1:start %s", get_csrf_token(self.request), ) if DEBUG_USERID: print("application:account:oauth1:start", self.request.active_useraccount_id) if self.request.active_useraccount_id: return HTTPSeeOther("/application/account/home") # setup the session storage if "3rdparty-app_oauth" not in self.request.session: self.request.session["3rdparty-app_oauth"] = {} # Store whether this OAuth attempt is to authenticate or authorize, so we # can provide the right try again link in case any of our calls to the # Twitter API fail. self.request.session["3rdparty-app_oauth"]["mode"] = "authorize" # If there was a valid ``next`` param in the query string, store it in the # session so we can redirect to it later on. self.request.session["3rdparty-app_oauth"][ "next"] = self.request.params.get("next") app_data = get_ApiExampleAppData() apiClient = CustomApiClient( app_key=app_data["client_key"], app_secret=app_data["client_secret"], client_args={"verify": False}, ) try: auth_props = apiClient.get_authentication_tokens( callback_url=app_data["callback_uri"]) self.request.session["3rdparty-app_oauth"][ "auth_url"] = auth_props["auth_url"] self.request.session["3rdparty-app_oauth"][ "oauth_token"] = auth_props["oauth_token"] self.request.session["3rdparty-app_oauth"][ "oauth_token_secret"] = auth_props["oauth_token_secret"] redirect_url = auth_props["auth_url"] return HTTPSeeOther(location=redirect_url) except ApiAuthError as exc: raise ValueError( "There are issues connecting with the Example Server API.") except ApiError as exc: error_dict = {"error": 1, "error_message": exc.msg} raise ValueError(exc.msg)
def account_home(self): if DEBUG_ROUTE: print("application:account:home", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("application:account:home %s", get_csrf_token(self.request)) if DEBUG_USERID: print("application:account:home", self.request.active_useraccount_id) if not self.request.active_useraccount_id: return HTTPSeeOther("/application/account/login-form") return "application|home|user=%s" % self.request.active_useraccount_id
def register(self): if DEBUG_ROUTE: print("application:flow-register", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("application:flow-register %s", get_csrf_token(self.request)) if DEBUG_USERID: print("application:flow-register", self.request.active_useraccount_id) if self.request.active_useraccount_id: return HTTPSeeOther("/application/account/home") return HTTPSeeOther("/application/flow-register/oauth2/start")
def account_login_submit(self): if DEBUG_ROUTE: print("application:account:login-submit", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("application:account:login-submit %s", get_csrf_token(self.request)) if DEBUG_USERID: print("application:account:login-submit", self.request.active_useraccount_id) self.request.session[ "active_useraccount_id"] = USERID_ACTIVE__APPLICATION return HTTPSeeOther("/application/account/home")
def account_login_form(self): if DEBUG_ROUTE: print("application:account:login-form", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("application:account:login-form %s", get_csrf_token(self.request)) if DEBUG_USERID: print("application:account:login-form", self.request.active_useraccount_id) if self.request.active_useraccount_id: return HTTPSeeOther("/application/account/home") return "application|login-form"
def authorized_callback_success(self): if DEBUG_ROUTE: print( "application:flow-register:oauth2:authorized-callback-success", get_csrf_token(self.request), ) if LOG_ROUTE: log.debug( "application:flow-register:oauth2:authorized-callback-success %s", get_csrf_token(self.request), ) if not self.request.active_useraccount_id: return HTTPSeeOther("/application/account/login-form") return ("example_app|authorized-callback-success|user=%s" % self.request.active_useraccount_id)
def registration_authorized_callback_success(self): if DEBUG_ROUTE: print( "application:flow-register:oauth1:authorized-callback-success", get_csrf_token(self.request), ) if LOG_ROUTE: log.debug( "application:flow-register:oauth1:authorized-callback-success|user=%s", get_csrf_token(self.request), ) if DEBUG_USERID: print( "application:account:register:oauth1:authorized-callback-success", self.request.active_useraccount_id, ) if not self.request.active_useraccount_id: return HTTPSeeOther("/application/account/login-form") # so let's just check to ensure we have the right number of active tokens (Client) _clientTokens = ( self.request.dbSession.query(Developer_oAuth1Client_TokenAccess). filter( Developer_oAuth1Client_TokenAccess.useraccount_id == USERID_ACTIVE__APPLICATION, Developer_oAuth1Client_TokenAccess.is_active == True, # noqa ).all()) assert len(_clientTokens) == 1 # so let's just check to ensure we have the right number of active tokens (Server) _serverTokens = ( self.request.dbSession.query(Developer_oAuth1Server_TokenAccess). filter( Developer_oAuth1Server_TokenAccess.useraccount_id == USERID_ACTIVE__AUTHORITY, Developer_oAuth1Server_TokenAccess.is_active == True, # noqa ).all()) assert len(_serverTokens) == 1 # and make sure the client/server tokens are the same assert (_serverTokens[0].oauth_token_secret == _clientTokens[0].oauth_token_secret) assert _serverTokens[0].oauth_token == _clientTokens[0].oauth_token assert _serverTokens[0]._realms == _clientTokens[0]._realms # yep, we good return ("application|register|authorized-callback-success|user=%s" % self.request.active_useraccount_id)
def _authorize_process(self): """process the form""" try: (result, formStash) = formhandling.form_validate( self.request, schema=Form_OAuthToken, csrf_token=get_csrf_token(self.request), ) if not result: raise formhandling.FormInvalid() if formStash.results["submit"] == "deny": # process deny raise HTTPSeeOther("/account/home") # accept! # this is decorated by `catch_errors_and_unavailability` and will raise an `OAuth1Error` return self.request.workspace.oAuth1Provider.endpoint__authorize__authorize( self.request.workspace.oAuth1_data) except (OAuth1Error, formhandling.FormInvalid) as exc: if isinstance(exc, OAuth1Error): self.request.workspace.oAuth1_Error = exc return formhandling.form_reprint(self.request, self._authorize_print)
def test_ok_with_good_csrf(self, pyramid_request): csrf_token = csrf.get_csrf_token(pyramid_request) pyramid_request.POST["csrf_token"] = csrf_token schema = ExampleCSRFSchema().bind(request=pyramid_request) # Does not raise schema.deserialize({})
def oauth2_revoke_token(self): if DEBUG_ROUTE: print("authority:oauth2:revoke_token", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:oauth2:revoke_token %s", get_csrf_token(self.request)) try: oauth2Provider = new_oauth2Provider(self.request) rval = oauth2Provider.endpoint__revoke_token() return rval except HTTPException: raise except Exception as exc: # raise custom errors in production raise exc
def obtain_token(self): """this default version calculates the client credentials as needed""" if DEBUG_ROUTE: print("authority:oauth2:flow_b:obtain_token", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:oauth2:flow_b:obtain_token %s", get_csrf_token(self.request)) try: oauth2Provider = new_oauth2Provider(self.request) rval = oauth2Provider.endopoint__token(credentials=None) return rval except HTTPException: raise except Exception as exc: # raise custom errors in production raise exc
def authorize(self): if DEBUG_ROUTE: print("authority:oauth1:authorize", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:oauth1:authorize %s", get_csrf_token(self.request)) if DEBUG_USERID: print("authority:oauth1:authorize", self.request.active_useraccount_id) if not self.request.active_useraccount_id: return HTTPSeeOther("/authority/account/login-form") try: # no matter what we do, we need to grab this data oauth1Provider = new_oauth1Provider(self.request) # this is decorated by `catch_errors_and_unavailability` and will raise an `OAuth1Error` oauth1_data = oauth1Provider.extract__endpoint_authorize_data() # grab the token to show the user or process oauth1_TokenRequest = ( self.request.dbSession.query( Developer_oAuth1Server_TokenRequest).filter( Developer_oAuth1Server_TokenRequest.oauth_token == oauth1_data["credentials"]["resource_owner_key"], Developer_oAuth1Server_TokenRequest.is_active == True, # noqa ).first()) if not oauth1_TokenRequest: raise ValueError("invalid token") self.request.workspace.oAuth1Provider = oauth1Provider self.request.workspace.oAuth1_data = oauth1_data self.request.workspace.oAuth1_TokenRequest = oauth1_TokenRequest if self.request.method == "POST": # this can raise an `OAuth1Error`, but it should be caught return self._authorize_process() return self._authorize_print() except OAuth1Error as exc: self.request.workspace.oAuth1_Error = exc return render_to_response( "templates/authorize-error.mako", {}, self.request, )
def obtain_token(self): """this endpoint does not accept client_credentials""" if DEBUG_ROUTE: print("authority:oauth2:flow_c:token_limited", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:oauth2:flow_c:token_limited %s", get_csrf_token(self.request)) try: oauth2Provider = new_oauth2ProviderLimited(self.request) rval = oauth2Provider.endopoint__token() return rval except HTTPException: raise except Exception as exc: # raise custom errors in production raise exc
def access_token(self): if DEBUG_ROUTE: print("authority:oauth1:access_token", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:oauth1:access_token %s", get_csrf_token(self.request)) if DEBUG_USERID: print("authority:oauth1:access_token", self.request.active_useraccount_id) try: provider = new_oauth1Provider(self.request) return provider.endpoint__access_token() except HTTPException: raise except Exception as exc: # raise custom errors in production raise exc
def protected_resource(self): """the resource is protected behind an oauth2 token validation.""" if DEBUG_ROUTE: print("authority:oauth2:protected_resource", get_csrf_token(self.request)) if LOG_ROUTE: log.debug("authority:oauth2:protected_resource %s", get_csrf_token(self.request)) oauth2Provider = new_oauth2Provider(self.request) scopes = ["platform.actor"] valid, req = oauth2Provider.verify_request(scopes) if not valid: raise HTTPForbidden() # dbTokens = self.request.dbSession.query(Developer_OAuth2Server_BearerToken).all() # pdb.set_trace() return "protected_resource"
def fetch_protected_resource(self): """ A user must log into ExampleApp and have an authorized token for the Authority system. This route will load the token and use it to make an oAuth2 request against the Authority system. """ if DEBUG_ROUTE: print( "application:account:fetch-protected-resource", get_csrf_token(self.request), ) if LOG_ROUTE: log.debug( "application:account:fetch-protected-resource %s", get_csrf_token(self.request), ) if not self.request.active_useraccount_id: return HTTPSeeOther("/application/account/login-form") # what is our token? clientToken = ( self.request.dbSession.query(Developer_OAuth2Client_BearerToken). filter( Developer_OAuth2Client_BearerToken.useraccount_id == self.request.active_useraccount_id, Developer_OAuth2Client_BearerToken.original_grant_type == "authorization_code", Developer_OAuth2Client_BearerToken.is_active == True, # noqa ).first()) if not clientToken: raise ValueError("no token for this user!") token_dict = { "access_token": clientToken.access_token, "token_type": "Bearer" } sess = OAuth2Session(client_id=OAUTH2__APP_KEY, token=token_dict) resp = sess.request( "GET", oauth2_utils.OAUTH2__URL_AUTHORITY_PROTECTED_RESOURCE) if resp.status_code != 200: raise ValueError("invalid") return resp.text
def obtain_token_alt(self): """ this alt version pre-calculates the client_credentials. 1. 'grant_type' in request.POST, grant_type=='client_credentials' 2. HTTP Basic Authorization contains username: client_id password: client_secret """ if DEBUG_ROUTE: print("authority:oauth2:flow_b:obtain_token_alt", get_csrf_token(self.request)) if LOG_ROUTE: log.debug( "authority:oauth2:flow_b:obtain_token_alt %s", get_csrf_token(self.request), ) try: # turn this into a username/password # HTTPBasicCredentials(username=u'OAUTH2APPKEYOAUTH2APPKEYOAUTH2APPKEYOAUTH2APPKEY', password=u'OAUTH2__APP_SECRET') credentials = extract_http_basic_credentials(self.request) credentials = ({ "username": credentials.username, "password": credentials.password } if credentials else {}) # logging.basicConfig() # _loggingOld = logging.getLogger().getEffectiveLevel() # logging.getLogger().setLevel(logging.DEBUG) oauth2Provider = new_oauth2Provider(self.request) rval = oauth2Provider.endopoint__token(credentials=credentials) return rval except HTTPException: raise except Exception as exc: # raise custom errors in production raise exc
def userLogin(request, login, password, appName): """ This and 'auth.logout' are the only rpc methods that does not subclass RpcBase for they must be invoked without valid user session. """ sess = DBSession() user = sess.query(Party).filter_by(login=login).first() if not user or not user.verifyPassword(password): raise RPCUserError('登录失败,请检查用户名和密码!') # Only those with defined permission are allowed if not user.extraData or appName not in user.extraData: raise RPCNotAllowedError('您无权登录当前应用。') # after user is authenticated, we cache the user object in redis sess.expunge_all() # detach from session request.session['user'] = user # copy so that we do not persist the token in the session user object ret = user.extraData[appName].copy() ret['csrfToken'] = get_csrf_token(request) return ret
def like_post_json(context: PostResource, request): """ JSON `like` action. This action is CSRF-safe thanks to: - Accepting only POST requests - Browsers cannot submit JSON from forms (only ``application/x-www-form-urlencoded``) - CORS/SOP prevent scripts on `external pages` from posting unless a CORS policy allows it. - Requires a CSRF-token In addition the user must have permission to perform the action. Abbreviations: - CORS = Cross-Origin Resource Sharing - SOP = Same Origin Policy """ request_body: dict = request.json_body # In case there is a CORS policy in place we also require the CSRF token # to be included in the JSON request. # # We can get the same effect by setting require_csrf=True which will # require the request to include an X-CSRF-Token header. # # Calling pyramid.csrf.check_csrf_token would also achieve the same thing # by checking the X-CSRF-Token header. csrf_token = request_body.get('csrf_token', '') expected_csrf_token = get_csrf_token(request) if not hmac.compare_digest(csrf_token, expected_csrf_token): raise BadCSRFToken() post = db.post.like_post(request.db, context.post.post_id) return post
def deferred_csrf_token(_node, kw): request = kw.get("request") return get_csrf_token(request)
def _callFUT(self, *args, **kwargs): from pyramid.csrf import get_csrf_token return get_csrf_token(*args, **kwargs)
def csrfToken(self): return get_csrf_token(self.request) \ if self.request.authenticated else None