def fxa_oauth_token(request): """Return OAuth token from authorization code. """ state = request.validated['state'] code = request.validated['code'] # Require on-going session stored_redirect = request.registry.cache.get(state) # Make sure we cannot try twice with the same code request.registry.cache.delete(state) if not stored_redirect: error_msg = 'The OAuth session was not found, please re-authenticate.' return http_error(httpexceptions.HTTPRequestTimeout(), errno=ERRORS.MISSING_AUTH_TOKEN, message=error_msg) # Trade the OAuth code for a longer-lived token auth_client = OAuthClient(server_url=fxa_conf(request, 'oauth_uri'), client_id=fxa_conf(request, 'client_id'), client_secret=fxa_conf(request, 'client_secret')) try: token = auth_client.trade_code(code) except fxa_errors.OutOfProtocolError: raise httpexceptions.HTTPServiceUnavailable() except fxa_errors.InProtocolError as error: logger.error(error) error_details = { 'name': 'code', 'location': 'querystring', 'description': 'Firefox Account code validation failed.' } raise_invalid(request, **error_details) return httpexceptions.HTTPFound(location='%s%s' % (stored_redirect, token))
def _get_auth_client(self, request): """Instantiate OAuthClient on first request but cache it. Hopefully this lets us retain the requests Session in the PyFxA class and keep the HTTP connection alive for longer. """ if self._auth_client is None: # Use PyFxa defaults if not specified server_url = fxa_conf(request, 'oauth_uri') auth_cache = self._get_cache(request) self._auth_client = OAuthClient(server_url=server_url, cache=auth_cache) return self._auth_client
def get_oauth_token(client_id=CLIENT_ID, oauth_server=OAUTH_SERVER, auth_server=AUTH_SERVER, email=EMAIL, password=PASSWORD): if password is None: raise Exception('You must set FXA_PASSWORD') print('Getting an oauth token from FxA') oauth_client = OAuthClient(client_id, server_url=oauth_server) session = Client(server_url=auth_server).login(email, password=password) assertion = session.get_identity_assertion(oauth_server) return oauth_client.authorize_token(assertion, scope="profile")
def fxa_ping(request): """Verify if the OAuth server is ready.""" server_url = fxa_conf(request, 'oauth_uri') oauth = None if server_url is not None: auth_client = OAuthClient(server_url=server_url) server_url = auth_client.server_url oauth = False try: heartbeat_url = urljoin(server_url, '/__heartbeat__') timeout = float(fxa_conf(request, 'heartbeat_timeout_seconds')) r = requests.get(heartbeat_url, timeout=timeout) r.raise_for_status() oauth = True except requests.exceptions.HTTPError: pass return oauth
def _verify_token(self, token, request): """Verify the token extracted from the Authorization header. This method stores the result in two locations to avoid hitting the auth remote server as much as possible: - on the request object, in case the Pyramid authentication methods like `effective_principals()` or `authenticated_userid()` are called several times during the request cycle; - in the cache backend, to reuse validated token from one request to another (during ``cache_ttl_seconds`` seconds.) """ # First check if this request was already verified. # `request.bound_data` is an attribute provided by Kinto to store # some data that is shared among sub-requests (e.g. default bucket # or batch requests) key = 'fxa_verified_token' if key in request.bound_data: return request.bound_data[key] # Use PyFxa defaults if not specified server_url = fxa_conf(request, 'oauth_uri') scope = aslist(fxa_conf(request, 'required_scope')) auth_cache = self._get_cache(request) auth_client = OAuthClient(server_url=server_url, cache=auth_cache) try: profile = auth_client.verify_token(token=token, scope=scope) user_id = profile['user'] except fxa_errors.OutOfProtocolError as e: logger.exception("Protocol error") raise httpexceptions.HTTPServiceUnavailable() except (fxa_errors.InProtocolError, fxa_errors.TrustError) as e: logger.debug("Invalid FxA token: %s" % e) user_id = None # Save for next call. request.bound_data[key] = user_id return user_id
def setUpClass(cls): # Create an ephemeral email account to use to create an FxA account cls.acct = TestEmailAccount() cls.client = Client(FXA_ACCOUNT_STAGE_HOST) cls.oauth_client = OAuthClient(CLIENT_ID, None, server_url=FXA_OAUTH_STAGE_HOST) cls.fxa_password = cls._generate_password() # Create an FxA account for these end-to-end tests cls.session = cls.client.create_account(cls.acct.email, password=cls.fxa_password) # Loop until we receive the verification email from FxA while not cls.acct.messages: time.sleep(0.5) cls.acct.fetch() # Find the message containing the verification code and verify the # code for m in cls.acct.messages: if 'x-verify-code' in m['headers']: cls.session.verify_email_code(m['headers']['x-verify-code']) # Create an OAuth token to be used for the end-to-end tests cls.oauth_token = cls.oauth_client.authorize_token(cls.session, SCOPE) cls.browserid_assertion = \ cls.session.get_identity_assertion(BROWSERID_AUDIENCE)
def verify_oauth_token(token, scope='profile', oauth_server=OAUTH_SERVER, client_id=CLIENT_ID): oauth_client = OAuthClient(client_id, server_url=oauth_server) return oauth_client.verify_token(token, scope=scope)