Example #1
0
 def test_that_macauth_can_use_per_node_hostname_secrets(self):
     with tempfile.NamedTemporaryFile() as sf:
         # Write some secrets to a file.
         sf.write("host1,0001:secret11,0002:secret12\n")
         sf.write("host2,0001:secret21,0002:secret22\n")
         sf.flush()
         # Configure the plugin to load them.
         config2 = pyramid.testing.setUp()
         config2.add_settings(self.DEFAULT_SETTINGS)
         config2.add_settings({
             "who.plugin.macauth.secrets_file": sf.name,
         })
         config2.include("mozsvc.user.whoauth")
         config2.commit()
         # It should accept a request signed with the old secret on host1.
         req = self._make_request(config=config2, environ={
             "HTTP_HOST": "host1",
         })
         id = tokenlib.make_token({"userid": 42}, secret="secret11")
         key = tokenlib.get_token_secret(id, secret="secret11")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request signed with the new secret on host1.
         req = self._make_request(config=config2, environ={
             "HTTP_HOST": "host1",
         })
         id = tokenlib.make_token({"userid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should reject a request signed with secret from other host.
         req = self._make_request(config=config2, environ={
             "HTTP_HOST": "host2",
         })
         id = tokenlib.make_token({"userid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(Exception, authenticated_userid, req)
         # It should accept a request signed with the new secret on host2.
         req = self._make_request(config=config2, environ={
             "HTTP_HOST": "host2",
         })
         id = tokenlib.make_token({"userid": 42}, secret="secret22")
         key = tokenlib.get_token_secret(id, secret="secret22")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should reject unknown hostnames.
         req = self._make_request(config=config2, environ={
             "HTTP_HOST": "host3",
         })
         id = tokenlib.make_token({"userid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(Exception, authenticated_userid, req)
def delete_service_data(user, secret, timeout=60):
    """Send a data-deletion request to the user's service node.

    This is a little bit of hackery to cause the user's service node to
    remove any data it still has stored for the user.  We simulate a DELETE
    request from the user's own account.
    """
    token = tokenlib.make_token(
        {
            "uid":
            user.uid,
            "node":
            user.node,
            "fxa_uid":
            user.email.split("@", 1)[0],
            "fxa_kid":
            format_key_id(user.keys_changed_at or user.generation,
                          binascii.unhexlify(user.client_state)),
        },
        secret=secret)
    secret = tokenlib.get_derived_secret(token, secret=secret)
    endpoint = PATTERN.format(uid=user.uid, node=user.node)
    auth = HawkAuth(token, secret)
    resp = requests.delete(endpoint, auth=auth, timeout=timeout)
    if resp.status_code >= 400 and resp.status_code != 404:
        resp.raise_for_status()
Example #3
0
def send_job(repo, server, cycles="", duration="", nodes="", redirect_url=""):
    mac_user = os.environ.get("MACAUTH_USER")
    mac_secret = os.environ.get("MACAUTH_SECRET")
    request = Request.blank(server.rstrip("/") + "/test")
    request.method = "POST"
    params = {
        "repo": repo,
        "cycles": cycles,
        "duration": duration,
        "nodes": nodes,
        "redirect_url": redirect_url,
        "api_call": 1,
    }

    request.body = urllib.urlencode(params)
    request.environ["CONTENT_TYPE"] = "application/x-www-form-urlencoded"

    if mac_user is not None:
        tokenid = tokenlib.make_token({"user": mac_user}, secret=mac_secret)
        key = tokenlib.get_token_secret(tokenid, secret=mac_secret)
        sign_request(request, tokenid, key)

    resp = request.get_response(proxy_exact_request)
    if resp.status_int == 401:
        raise ValueError("Authorization Failed!")

    job_id = resp.json["job_id"]
    return server.rstrip("/") + "/test/" + job_id
def delete_service_data(config, service, user, timeout=60):
    """Send a data-deletion request to the user's service node.

    This is a little bit of hackery to cause the user's service node to
    remove any data it still has stored for the user.  We simulate a DELETE
    request from the user's own account.
    """
    secrets = config.registry.settings['tokenserver.secrets']
    pattern = config.registry['endpoints_patterns'][service]
    node_secrets = secrets.get(user.node)
    if not node_secrets:
        msg = "The node %r does not have any shared secret" % (user.node,)
        raise ValueError(msg)
    token = tokenlib.make_token({
        "uid": user.uid,
        "node": user.node,
        "fxa_uid": user.email.split("@", 1)[0],
        "fxa_kid": user.client_state
    }, secret=node_secrets[-1])
    secret = tokenlib.get_derived_secret(token, secret=node_secrets[-1])
    endpoint = pattern.format(uid=user.uid, service=service, node=user.node)
    auth = HawkAuth(token, secret)
    resp = requests.delete(endpoint, auth=auth, timeout=timeout)
    if resp.status_code >= 400 and resp.status_code != 404:
        resp.raise_for_status()
Example #5
0
 def test_get_token_secret_is_deprecated(self):
     token = tokenlib.make_token({"hello": "world"})
     with warnings.catch_warnings(record=True) as w:
         warnings.simplefilter("default")
         tokenlib.get_token_secret(token)
         self.assertEquals(len(w), 1)
         self.assertEquals(w[0].category, DeprecationWarning)
Example #6
0
def users_create():
    response.content_type = 'application/json; charset=utf-8'
    res = {
        'username': request.forms.get('username'),
        'password': request.forms.get('password'),
        'email': request.forms.get('email')
    }

    db = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    secret_token = tokenlib.make_token(res, secret="picoteo grafico")
    response.status = 200
    sql = "INSERT INTO users (username, email, password, session_token) "
    sql += "VALUES ('%s', '%s', '%s', '%s')" % (res['username'], res['email'],
                                                res['password'], secret_token)
    db.execute(sql)
    conn.commit()
    db.close()

    return {
        'status': 'success',
        'data': {
            'message': 'user created',
            'session_token': secret_token
        }
    }
def login_method(request):
    if request.method != "POST":
        return HttpResponseNotAllowed(permitted_methods=['POST'])
    username = request.POST.get(POST_USERNAME)
    password = request.POST.get(POST_PASSWORD)
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
        # get or make secret for token
            if unique_token_key.objects.all().count() == 0:
                randomString = str(random.randint(0, 32767))
                secret = randomString
                uniqueObject = unique_token_key(key_id=1, key=randomString)
                uniqueObject.save()
            else:
                secret = unique_token_key.objects.get(pk=1).key
            token = tokenlib.make_token({"userid": user.id}, secret=secret)
            template = loader.get_template('CPBet/homepage.html')
            context = RequestContext(request, {TOKEN: token})
            return HttpResponse(template.render(context))
    else:
        return HttpResponse(json.dumps({"Status": STATUS_WRONG_USERNAME_OR_PASSWORD,
                                        "Error": "Username or password incorrect."},
                                       sort_keys=True))
def send_job(repo, server, cycles='', duration='', nodes='', redirect_url=''):
    mac_user = os.environ.get('MACAUTH_USER')
    mac_secret = os.environ.get('MACAUTH_SECRET')
    request = Request.blank(server.rstrip('/') + '/test')
    request.method = 'POST'
    params = {
        'repo': repo,
        'cycles': cycles,
        'duration': duration,
        'nodes': nodes,
        'redirect_url': redirect_url,
        'api_call': 1
    }

    request.body = urllib.urlencode(params)
    request.environ['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'

    if mac_user is not None:
        tokenid = tokenlib.make_token({"user": mac_user}, secret=mac_secret)
        key = tokenlib.get_token_secret(tokenid, secret=mac_secret)
        sign_request(request, tokenid, key)

    resp = request.get_response(proxy_exact_request)
    if resp.status_int == 401:
        raise ValueError("Authorization Failed!")

    job_id = resp.json['job_id']
    return server.rstrip('/') + '/test/' + job_id
Example #9
0
 def test_get_token_secret_is_deprecated(self):
     token = tokenlib.make_token({"hello": "world"})
     with warnings.catch_warnings(record=True) as w:
         warnings.simplefilter("default")
         tokenlib.get_token_secret(token)
         self.assertEquals(len(w), 1)
         self.assertEquals(w[0].category, DeprecationWarning)
Example #10
0
def delete_service_data(config, service, user, timeout=60, settings=None):
    """Send a data-deletion request to the user's service node.

    This is a little bit of hackery to cause the user's service node to
    remove any data it still has stored for the user.  We simulate a DELETE
    request from the user's own account.
    """
    secrets = config.registry.settings['tokenserver.secrets']
    pattern = config.registry['endpoints_patterns'][service]
    node_secrets = secrets.get(user.node)
    if not node_secrets:
        msg = "The node %r does not have any shared secret" % (user.node, )
        raise ValueError(msg)
    token = tokenlib.make_token(
        {
            "uid":
            user.uid,
            "node":
            user.node,
            "fxa_uid":
            user.email.split("@", 1)[0],
            "fxa_kid":
            format_key_id(user.keys_changed_at or user.generation,
                          user.client_state.decode('hex')),
        },
        secret=node_secrets[-1])
    secret = tokenlib.get_derived_secret(token, secret=node_secrets[-1])
    endpoint = pattern.format(uid=user.uid, service=service, node=user.node)
    auth = HawkAuth(token, secret)
    if settings and settings.dryrun:
        return
    resp = requests.delete(endpoint, auth=auth, timeout=timeout)
    if resp.status_code >= 400 and resp.status_code != 404:
        resp.raise_for_status()
Example #11
0
def return_token(request):
    # at this stage, we are sure that the assertion, application and version
    # number were valid, so let's build the authentication token and return it.

    backend = request.registry.getUtility(INodeAssignment)
    email = request.validated['assertion']['email']
    application = request.validated['application']
    version = request.validated['version']
    pattern = request.validated['pattern']
    service = get_service_name(application, version)

    # get the node or allocate one if none is already set
    uid, node = backend.get_node(email, service)
    if node is None or uid is None:
        uid, node = backend.allocate_node(email, service)

    secrets = request.registry.settings['tokenserver.secrets_file']
    node_secrets = secrets.get(node)
    if not node_secrets:
        raise Exception("The specified node does not have any shared secret")
    secret = node_secrets[-1]  # the last one is the most recent one

    token = make_token({'uid': uid, 'service_entry': node}, secret=secret)
    # XXX needs to be renamed as 'get_derived_secret' because
    # it's not clear here it's a derived
    secret = get_token_secret(token, secret=secret)

    api_endpoint = pattern.format(uid=uid, service=service, node=node)

    # FIXME add the algo used to generate the token
    return {'id': token, 'key': secret, 'uid': uid,
            'api_endpoint': api_endpoint}
Example #12
0
 def test_convenience_functions(self):
     token = tokenlib.make_token({"hello": "world"})
     self.assertEquals(tokenlib.parse_token(token)["hello"], "world")
     self.assertRaises(ValueError, tokenlib.parse_token, token, secret="X")
     self.assertEquals(tokenlib.get_token_secret(token),
                       tokenlib.get_token_secret(token))
     self.assertNotEquals(tokenlib.get_token_secret(token),
                          tokenlib.get_token_secret(token, secret="X"))
Example #13
0
def generate_token(user_id):
    if tokens_collection.find({"user_id": user_id}).count() == 0:
        logging.info('creating token...')
        token = tokenlib.make_token({"user_id": user_id}, secret="I_LIKE_UNICORNS")
        return token
    else:
        logging.info("token exist...")
        data_token = tokens_collection.find_one({"user_id": user_id})
        token = str(data_token['key'])
        if validate_token(token):
            return token
        else:
            logging.info('token expired...')
            logging.info('creating a new...')
            tokens_collection.remove({'_id': data_token['_id']})
            token = tokenlib.make_token({"user_id": user_id}, secret="I_LIKE_UNICORNS")
            return token
Example #14
0
 def test_invalid_callurl_token_returns_400(self):
     # Let's forge a call token with an invalid secret.
     invalid_token = tokenlib.make_token({'userid': 'h4x0r'},
                                         secret='I AM MEAN')
     resp = self.app.get('/calls/%s' % invalid_token, status=400)
     self.assertEquals(resp.json['status'], 'error')
     self.assertEquals(resp.json['errors'][0]['description'],
                       'token has invalid signature')
Example #15
0
 def veryfi(self,username,password):
     if username=="123123" and password == "123123":
         token_ram = tokenlib.make_token({"user":username})[:10]
         # token太长,有时gw会截断,重新生成,导致认证失败
         tok[username] = token_ram
         raise cherrypy.HTTPRedirect("http://172.16.100.1:8060/wifidog/auth?token=%s"%token_ram,status=302)
     else:
         return "wrong user or passwd!"
Example #16
0
 def test_convenience_functions(self):
     token = tokenlib.make_token({"hello": "world"})
     self.assertEquals(tokenlib.parse_token(token)["hello"], "world")
     self.assertRaises(ValueError, tokenlib.parse_token, token, secret="X")
     self.assertEquals(tokenlib.get_token_secret(token),
                       tokenlib.get_token_secret(token))
     self.assertNotEquals(tokenlib.get_token_secret(token),
                          tokenlib.get_token_secret(token, secret="X"))
Example #17
0
 def _generate_token_credentials(self):
     """Pick an identity, log in and generate the auth token."""
     # If the server_url has a hash fragment, it's a storage node and
     # that's the secret.  Otherwise it's a token server url.
     uid = random.randint(1, 1000000)
     url = urlparse(self.server_url)
     if url.fragment:
         endpoint = url._replace(fragment="", path="/1.5/" + str(uid))
         self.endpoint_url = urlunparse(endpoint)
         data = {
             "uid": uid,
             "node": urlunparse(url._replace(fragment="")),
             "expires": time.time() + ASSERTION_LIFETIME,
         }
         self.auth_token = tokenlib.make_token(data, secret=url.fragment)
         self.auth_secret = tokenlib.get_derived_secret(self.auth_token,
                                                        secret=url.fragment)
     else:
         email = "user%s@%s" % (uid, MOCKMYID_DOMAIN)
         exp = time.time() + ASSERTION_LIFETIME + HawkAuth.timeskew
         assertion = browserid.tests.support.make_assertion(
             email=email,
             audience=self.server_url,
             issuer=MOCKMYID_DOMAIN,
             issuer_keypair=(None, MOCKMYID_PRIVATE_KEY),
             exp=int(exp * 1000),
         )
         token_url = self.server_url + "/1.0/sync/1.5"
         response = self.session.get(token_url,
                                     headers={
                                         "Authorization":
                                         "BrowserID " + assertion,
                                     })
         # Maybe timeskew between client and server?
         if response.status_code == 401:
             server_time = int(response.headers["X-Timestamp"])
             HawkAuth.timeskew = server_time - int(time.time())
             exp = time.time() + ASSERTION_LIFETIME + HawkAuth.timeskew
             assertion = browserid.tests.support.make_assertion(
                 email=email,
                 audience=self.server_url,
                 issuer=MOCKMYID_DOMAIN,
                 issuer_keypair=(None, MOCKMYID_PRIVATE_KEY),
                 exp=int(exp * 1000),
             )
             response = self.session.get(token_url,
                                         headers={
                                             "Authorization":
                                             "BrowserID " + assertion,
                                         })
         response.raise_for_status()
         credentials = response.json()
         self.auth_token = credentials["id"].encode('ascii')
         self.auth_secret = credentials["key"].encode('ascii')
         self.endpoint_url = credentials["api_endpoint"]
     return self.auth_token, self.auth_secret, self.endpoint_url
 def test_valid_oauth_request(self):
     oauth_token = self.oauth_token
     headers = {
         'Authorization': 'Bearer %s' % oauth_token,
         'X-KeyID': '1234-qqo'
     }
     # Send a valid request, allocating a new user
     res = self.app.get('/1.0/sync/1.5', headers=headers)
     fxa_uid = self.session.uid
     # Retrieve the user from the database
     user = self._get_user(res.json['uid'])
     # First, let's verify that the token we received is valid. To do this,
     # we can unpack the hawk header ID into the payload and its signature
     # and then construct a tokenlib token to compute the signature
     # ourselves. To obtain a matching signature, we use the same secret as
     # is used by Tokenserver.
     raw = urlsafe_b64decode(res.json['id'])
     payload = raw[:-32]
     signature = raw[-32:]
     payload_dict = json.loads(payload.decode('utf-8'))
     # The `id` payload should include a field indicating the origin of the
     # token
     self.assertEqual(payload_dict['tokenserver_origin'], 'rust')
     signing_secret = self.TOKEN_SIGNING_SECRET
     expected_token = tokenlib.make_token(payload_dict,
                                          secret=signing_secret)
     expected_signature = urlsafe_b64decode(expected_token)[-32:]
     # Using the #compare_digest method here is not strictly necessary, as
     # this is not a security-sensitive situation, but it's good practice
     self.assertTrue(hmac.compare_digest(expected_signature, signature))
     # Check that the given key is a secret derived from the hawk ID
     expected_secret = tokenlib.get_derived_secret(res.json['id'],
                                                   secret=signing_secret)
     self.assertEqual(res.json['key'], expected_secret)
     # Check to make sure the remainder of the fields are valid
     self.assertEqual(res.json['uid'], user['uid'])
     self.assertEqual(res.json['api_endpoint'],
                      '%s/1.5/%s' % (self.NODE_URL, user['uid']))
     self.assertEqual(res.json['duration'], DEFAULT_TOKEN_DURATION)
     self.assertEqual(res.json['hashalg'], 'sha256')
     self.assertEqual(res.json['hashed_fxa_uid'],
                      self._fxa_metrics_hash(fxa_uid)[:32])
     self.assertEqual(res.json['node_type'], 'spanner')
     # The response should have an X-Timestamp header that contains the
     # number of seconds since the UNIX epoch
     self.assertIn('X-Timestamp', res.headers)
     self.assertIsNotNone(int(res.headers['X-Timestamp']))
     token = self.unsafelyParseToken(res.json['id'])
     self.assertIn('hashed_device_id', token)
     self.assertEqual(token["uid"], res.json["uid"])
     self.assertEqual(token["fxa_uid"], fxa_uid)
     self.assertEqual(token["fxa_kid"], "0000000001234-qqo")
     self.assertNotEqual(token["hashed_fxa_uid"], token["fxa_uid"])
     self.assertEqual(token["hashed_fxa_uid"], res.json["hashed_fxa_uid"])
     self.assertIn("hashed_device_id", token)
Example #19
0
def invite(request, team_id):
    team = Team.objects.get(team_id=team_id)
    token = make_token({
        "team_id": team_id,
        "team_name": team.team_name
    },
                       timeout=team.moderator_expire,
                       secret=SECRET_SALT)
    Token(token=token).save()
    context = {'token': token}
    return render(request, 'leave_bot/invite.html', context)
    def test_valid_browserid_request(self):
        assertion = self.browserid_assertion
        headers = {
            'Authorization': 'BrowserID %s' % assertion,
            'X-Client-State': 'aaaa'
        }
        # Send a valid request, allocating a new user
        res = self.app.get('/1.0/sync/1.5', headers=headers)
        fxa_uid = self.session.uid
        # Retrieve the user from the database
        user = self._get_user(res.json['uid'])
        # First, let's verify that the token we received is valid. To do this,
        # we can unpack the hawk header ID into the payload and its signature
        # and then construct a tokenlib token to compute the signature
        # ourselves. To obtain a matching signature, we use the same secret as
        # is used by Tokenserver.
        raw = urlsafe_b64decode(res.json['id'])
        payload = raw[:-32]
        signature = raw[-32:]
        payload_dict = json.loads(payload.decode('utf-8'))

        signing_secret = self.TOKEN_SIGNING_SECRET
        expected_token = tokenlib.make_token(payload_dict,
                                             secret=signing_secret)
        expected_signature = urlsafe_b64decode(expected_token)[-32:]
        # Using the #compare_digest method here is not strictly necessary, as
        # this is not a security-sensitive situation, but it's good practice
        self.assertTrue(hmac.compare_digest(expected_signature, signature))
        # Check that the given key is a secret derived from the hawk ID
        expected_secret = tokenlib.get_derived_secret(res.json['id'],
                                                      secret=signing_secret)
        self.assertEqual(res.json['key'], expected_secret)
        # Check to make sure the remainder of the fields are valid
        self.assertEqual(res.json['uid'], user['uid'])
        self.assertEqual(res.json['api_endpoint'],
                         '%s/1.5/%s' % (self.NODE_URL, user['uid']))
        self.assertEqual(res.json['duration'], DEFAULT_TOKEN_DURATION)
        self.assertEqual(res.json['hashalg'], 'sha256')
        self.assertEqual(res.json['hashed_fxa_uid'],
                         self._fxa_metrics_hash(fxa_uid)[:32])
        self.assertEqual(res.json['node_type'], 'spanner')

        token = self.unsafelyParseToken(res.json['id'])
        self.assertIn('hashed_device_id', token)
        self.assertEqual(token["uid"], res.json["uid"])
        self.assertEqual(token["fxa_uid"], fxa_uid)
        assertion = self.browserid_assertion
        keys_changed_at = \
            self._extract_keys_changed_at_from_assertion(assertion)
        self.assertEqual(token["fxa_kid"], "%s-qqo" % str(keys_changed_at))
        self.assertNotEqual(token["hashed_fxa_uid"], token["fxa_uid"])
        self.assertEqual(token["hashed_fxa_uid"], res.json["hashed_fxa_uid"])
        self.assertIn("hashed_device_id", token)
Example #21
0
 def _generate_token_credentials(self):
     """Pick an identity, log in and generate the auth token."""
     # If the server_url has a hash fragment, it's a storage node and
     # that's the secret.  Otherwise it's a token server url.
     uid = random.randint(1, 1000000)
     url = urlparse(self.server_url)
     if url.fragment:
         endpoint = url._replace(fragment="", path="/1.5/" + str(uid))
         self.endpoint_url = urlunparse(endpoint)
         data = {
             "uid": uid,
             "node": urlunparse(url._replace(fragment="")),
             "expires": time.time() + ASSERTION_LIFETIME,
         }
         self.auth_token = tokenlib.make_token(data, secret=url.fragment)
         self.auth_secret = tokenlib.get_derived_secret(self.auth_token,
                                                        secret=url.fragment)
     else:
         email = "user%s@%s" % (uid, MOCKMYID_DOMAIN)
         exp = time.time() + ASSERTION_LIFETIME + HawkAuth.timeskew
         assertion = browserid.tests.support.make_assertion(
             email=email,
             audience=self.server_url,
             issuer=MOCKMYID_DOMAIN,
             issuer_keypair=(None, MOCKMYID_PRIVATE_KEY),
             exp=int(exp * 1000),
         )
         token_url = self.server_url + "/1.0/sync/1.5"
         response = self.session.get(token_url, headers={
             "Authorization": "BrowserID " + assertion,
         })
         # Maybe timeskew between client and server?
         if response.status_code == 401:
             server_time = int(response.headers["X-Timestamp"])
             HawkAuth.timeskew = server_time - int(time.time())
             exp = time.time() + ASSERTION_LIFETIME + HawkAuth.timeskew
             assertion = browserid.tests.support.make_assertion(
                 email=email,
                 audience=self.server_url,
                 issuer=MOCKMYID_DOMAIN,
                 issuer_keypair=(None, MOCKMYID_PRIVATE_KEY),
                 exp=int(exp * 1000),
             )
             response = self.session.get(token_url, headers={
                 "Authorization": "BrowserID " + assertion,
             })
         response.raise_for_status()
         credentials = response.json()
         self.auth_token = credentials["id"].encode('ascii')
         self.auth_secret = credentials["key"].encode('ascii')
         self.endpoint_url = credentials["api_endpoint"]
     return self.auth_token, self.auth_secret, self.endpoint_url
    def _get_public_token(self):
        """ When asked for a new public token, it will generate a new public
        key, with a new expiration date
        """

        secret = IAnnotations(self)[SECRET_KEY]
        public = tokenlib.make_token({}, secret=secret, timeout=TIMEOUT)

        expiry_date = date.today() + timedelta(seconds=TIMEOUT)
        IAnnotations(self)[TOKEN_EXPIRES_KEY] = expiry_date
        IAnnotations(self)[TOKEN_KEY] = public

        return public
    def _get_public_token(self):
        """ When asked for a new public token, it will generate a new public
        key, with a new expiration date
        """

        secret = IAnnotations(self)[SECRET_KEY]
        public = tokenlib.make_token({}, secret=secret, timeout=TIMEOUT)

        expiry_date = date.today() + timedelta(seconds=TIMEOUT)
        IAnnotations(self)[TOKEN_EXPIRES_KEY] = expiry_date
        IAnnotations(self)[TOKEN_KEY] = public

        return public
    def encode_mac_id(self, request, userid=None, **data):
        """Encode the given userid into a MACAuth token id and secret key.

        This method is essentially the reverse of decode_mac_id.  Given
        a userid, it returns a MACAuth id and corresponding secret key.
        It is not needed for consuming authentication tokens, but is very
        useful when building them for testing purposes.
        """
        if userid is not None:
            data["userid"] = userid
        tokenid = tokenlib.make_token(data, secret=self.master_secret)
        secret = tokenlib.get_token_secret(tokenid, secret=self.master_secret)
        return tokenid, secret
Example #25
0
    def encode_mac_id(self, request, userid):
        """Encode the given userid into a MAC id and secret key.

        This method is essentially the reverse of decode_mac_id.  It is
        not needed for consuming authentication tokens, but is very useful
        when building them for testing purposes.
        """
        # There might be multiple secrets in use, if we're in the
        # process of transitioning from one to another.  Always use
        # the last one aka the "most recent" secret.
        secret = self._get_token_secrets(request)[-1]
        tokenid = tokenlib.make_token({"uid": userid}, secret=secret)
        key = tokenlib.get_token_secret(tokenid, secret=secret)
        return tokenid, key
Example #26
0
    def encode_mac_id(self, request, userid):
        """Encode the given userid into a MAC id and secret key.

        This method is essentially the reverse of decode_mac_id.  It is
        not needed for consuming authentication tokens, but is very useful
        when building them for testing purposes.
        """
        # There might be multiple secrets in use, if we're in the
        # process of transitioning from one to another.  Always use
        # the last one aka the "most recent" secret.
        secret = self._get_token_secrets(request)[-1]
        tokenid = tokenlib.make_token({"uid": userid}, secret=secret)
        key = tokenlib.get_token_secret(tokenid, secret=secret)
        return tokenid, key
    def encode_hawk_id(  # pylint: disable=E0202, W0613
            self, request, userid=None, **data):
        """Encode the given userid into a Hawk token id and secret key.

        This method is essentially the reverse of decode_hawk_id.  Given
        a userid, it returns a Hawk id and corresponding secret key.
        It is not needed for consuming authentication tokens, but is very
        useful when building them for testing purposes.
        """
        if userid is not None:
            data["userid"] = userid
        master_secret = self.master_secret
        tokenid = tokenlib.make_token(data, secret=master_secret)
        secret = tokenlib.get_derived_secret(tokenid, secret=master_secret)
        return tokenid, secret
Example #28
0
def create_token():
    expires = int(time.time()) + DURATION
    token_data = {
        'uid': LEGACY_UID,
        'node': NODE,
        'expires': expires,
        'fxa_uid': FXA_UID,
        'fxa_kid': FXA_KID,
        'hashed_fxa_uid': metrics_hash(FXA_UID),
        'hashed_device_id': metrics_hash(DEVICE_ID),
        'salt': SALT,
    }
    token = tokenlib.make_token(token_data, secret=SECRET)
    key = tokenlib.get_derived_secret(token, secret=SECRET)
    return token, key, expires, SALT
    def encode_hawk_id(self, request, data):
        """Encode data dict into Hawk id token and secret key.

        This method is essentially the reverse of decode_hawk_id.  Given a
        dict of identity data, it encodes it into a unique Hawk id token and
        corresponding secret key.  By default it uses the tokenlib library,
        but plugin instances may override this method with another callable
        the config file.

        This method is not needed when consuming auth tokens, but is very
        handy when building them for testing purposes.
        """
        id = tokenlib.make_token(data, secret=self.master_secret)
        secret = tokenlib.get_token_secret(id, secret=self.master_secret)
        return id, secret
Example #30
0
def create_token(args):
    expires = int(time.time()) + args.duration
    token_data = {
        'uid': args.uid,
        'node': args.node,
        'expires': expires,
        'fxa_uid': args.fxa_uid,
        'fxa_kid': args.fxa_kid,
        'hashed_fxa_uid': metrics_hash(args, args.fxa_uid),
        'hashed_device_id': metrics_hash(args, args.device_id),
        'salt': SALT,
    }
    token = tokenlib.make_token(token_data, secret=args.secret)
    key = tokenlib.get_derived_secret(token, secret=args.secret)
    return token, key, expires, SALT
    def encode_hawk_id(self, request, data):
        """Encode data dict into Hawk id token and secret key.

        This method is essentially the reverse of decode_hawk_id.  Given a
        dict of identity data, it encodes it into a unique Hawk id token and
        corresponding secret key.  By default it uses the tokenlib library,
        but plugin instances may override this method with another callable
        the config file.

        This method is not needed when consuming auth tokens, but is very
        handy when building them for testing purposes.
        """
        id = tokenlib.make_token(data, secret=self.master_secret)
        secret = tokenlib.get_token_secret(id, secret=self.master_secret)
        return id, secret
Example #32
0
 def encode_hawk_id(self, request, userid, extra=None):
     """Encode the given userid into a Hawk id and secret key.
     This method is essentially the reverse of decode_hawk_id.  It is
     not needed for consuming authentication tokens, but is very useful
     when building them for testing purposes.
     """
     node_name = self._get_node_name(request)
     # There might be multiple secrets in use, if we're in the
     # process of transitioning from one to another.  Always use
     # the last one aka the "most recent" secret.
     secret = self._get_token_secrets(node_name)[-1]
     data = {"uid": userid, "node": node_name}
     if extra is not None:
         data.update(extra)
     tokenid = tokenlib.make_token(data, secret=secret)
     key = tokenlib.get_derived_secret(tokenid, secret=secret)
     return tokenid, key
    def encode_hawk_id(self, request, userid, extra=None):
        """Encode the given userid into a Hawk id and secret key.

        This method is essentially the reverse of decode_hawk_id.  It is
        not needed for consuming authentication tokens, but is very useful
        when building them for testing purposes.

        Unlike its superclass method, this one allows the caller to specify
        a dict of additional user data to include in the auth token.
        """
        node_name = self._get_node_name(request)
        secret = self._get_token_secrets(node_name)[-1]
        data = {"uid": userid, "node": node_name}
        if extra is not None:
            data.update(extra)
        tokenid = tokenlib.make_token(data, secret=secret)
        key = tokenlib.get_derived_secret(tokenid, secret=secret)
        return tokenid, key
Example #34
0
def login():
    data = json.loads(flask.request.data)
    try:
        managers.email_password_correct(data)
    except managers.Incorrect as exc:
        abort(str(exc), 400)
    control = controller.Controller(flask.current_app.config)
    try:
        user_id = control.login(data["email"], data["password"])
    except managers.NotFound as exc:
        abort(str(exc), 401)
    except managers.NotActive as exc:
        abort(str(exc), 400)
    except managers.SecurityError as exc:
        abort(str(exc), 401)
    token = tokenlib.make_token(
        {"user_id": user_id},
        secret=flask.current_app.config["security"]["key"])
    return flask.jsonify({"token": token}), 200
Example #35
0
def register_method(request):
    if request.method != "POST":
        return HttpResponseNotAllowed(permitted_methods=['POST'])
    # make sure u verify that the 2 passwords are the same
    username = request.POST.get(POST_USERNAME)
    password = request.POST.get(POST_PASSWORD)
    email = request.POST.get(POST_EMAIL)
    try:
    # we create the User object
        new_user = User.objects.create_user(
            username=username,
            password=password,
            email=email,
        )
        new_user.save()
    except:
        return HttpResponse(json.dumps({"Status": STATUS_DUPLICATE,
                                        "Error": "User could not be created. Duplicate username or email"},
                            sort_keys=True))
    # authenticate newly formed user
    # is it possible to use new_user references????
    user = authenticate(username=username, password=password)
    if user is not None:
        if user.is_active:
        # we log in and create token
            login(request, user)
            print "User has been authenticated."
        # get or make secret for token
            if unique_token_key.objects.all().count() == 0:
                randomString = str(random.randint(0, 32767))
                secret = randomString
                uniqueObject = unique_token_key(key_id=1, key=randomString)
                uniqueObject.save()
            else:
                secret = unique_token_key.objects.get(pk=1).key
            token = tokenlib.make_token({"userid": user.id}, secret=secret)
        template = loader.get_template('CPBet/homepage.html')
        context = RequestContext(request, {TOKEN: token})
        return HttpResponse(template.render(context))
    else:
        return HttpResponse(json.dumps({"Status": STATUS_NOT_YET,
                                        "Error": "The account has not been created yet."},
                                       sort_keys=True))
Example #36
0
def login_user():
    email = request.form['email']
    password = request.form['password']
    errors = {}
    print(email, password)
    if find_userbyEmail(email) is not None:
        from models.users import User
        user = db.session.query(User).filter_by(email=email).first()
        if user.password == password:
            token = tokenlib.make_token({
                "id": user.id,
                "admin": user.admin
            },
                                        secret=super_duper_secret,
                                        timeout=60 * 60)
            from models.users import Profile
            prof = db.session.query(Profile).filter_by(user_id=user.id).first()
            if user.admin == True:
                print("admin", user)
                return json.dumps({
                    "success": True,
                    "token": token,
                    "profile_url": "/admin_page",
                    "errors": errors
                })
            print("Normal user", user)
            return json.dumps({
                "success":
                True,
                "token":
                token,
                "profile_url":
                "/profile/{0}.{1}".format(prof.name, prof.surname),
                "errors":
                errors
            })
        else:
            errors['password'] = "******"
            return json.dumps({"success": False, "errors": errors})
    else:
        print("email and password worng")
        errors['email'] = "No user with this email exists"
        return json.dumps({"success": False, "errors": errors})
 def login(self, username: str, password: str):
     user = User.objects(username=username,
                         password=sha256(
                             password.encode()).hexdigest()).first()
     if user:
         token = tokenlib.make_token(
             {
                 "user_id": str(user.id),
                 'username': username,
                 'password': password,
                 'random_value': random.randint(0, 1000000)
             },
             secret=SECRET_KEY)
         user.isAuth = True
         user.token = token
         user.date_last_login = timezone.now()
         user.save()
         return token
     else:
         raise UnknownUserError(username)
Example #38
0
def delete_service_data(config, service, uid, node, timeout=60):
    """Send a data-deletion request to the user's service node.

    This is a little bit of hackery to cause the user's service node to
    remove any data it still has stored for the user.  We simulate a DELETE
    request from the user's own account.
    """
    secrets = config.registry.settings['tokenserver.secrets']
    pattern = config.registry['endpoints_patterns'][service]
    node_secrets = secrets.get(node)
    if not node_secrets:
        msg = "The node %r does not have any shared secret" % (node, )
        raise ValueError(msg)
    user = {"uid": uid, "node": node}
    token = tokenlib.make_token(user, secret=node_secrets[-1])
    secret = tokenlib.get_derived_secret(token, secret=node_secrets[-1])
    endpoint = pattern.format(uid=uid, service=service, node=node)
    auth = HawkAuth(token, secret)
    resp = requests.delete(endpoint, auth=auth, timeout=timeout)
    if resp.status_code >= 400 and resp.status_code != 404:
        resp.raise_for_status()
Example #39
0
def send_job(repo, server, cycles='', duration='', nodes='', redirect_url=''):
    mac_user = os.environ.get('MACAUTH_USER')
    mac_secret = os.environ.get('MACAUTH_SECRET')
    request = Request.blank(server.rstrip('/') + '/test')
    request.method = 'POST'
    params = {'repo': repo, 'cycles': cycles, 'duration': duration,
              'nodes': nodes, 'redirect_url': redirect_url,
              'api_call': 1}

    request.body = urllib.urlencode(params)
    request.environ['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'

    if mac_user is not None:
        tokenid = tokenlib.make_token({"user": mac_user}, secret=mac_secret)
        key = tokenlib.get_token_secret(tokenid, secret=mac_secret)
        sign_request(request, tokenid, key)

    resp = request.get_response(proxy_exact_request)
    if resp.status_int == 401:
        raise ValueError("Authorization Failed!")

    job_id = resp.json['job_id']
    return server.rstrip('/') + '/test/' + job_id
Example #40
0
#coding:utf-8
#!/usr/bin/env python
#Created by Charles on 2018/3/1


import tokenlib
import tokenize

print (tokenlib.make_token({"user":12},))


def ssx(**kwargs):
    print(kwargs["ss"])



ssx(**{"ss":21})
Example #41
0
def return_token(request):
    """This service does the following process:

    - validates the BrowserID assertion provided on the Authorization header
    - allocates when necessary a node to the user for the required service
    - checks generation numbers and x-client-state header
    - returns a JSON mapping containing the following values:

        - **id** -- a signed authorization token, containing the
          user's id for hthe application and the node.
        - **secret** -- a secret derived from the shared secret
        - **uid** -- the user id for this servic
        - **api_endpoint** -- the root URL for the user for the service.
    """
    # at this stage, we are sure that the assertion, application and version
    # number were valid, so let's build the authentication token and return it.
    backend = request.registry.getUtility(INodeAssignment)
    settings = request.registry.settings
    email = request.validated['authorization']['email']
    try:
        idp_claims = request.validated['authorization']['idpClaims']
        generation = idp_claims['fxa-generation']
        if not isinstance(generation, (int, long)):
            raise _unauthorized("invalid-generation")
    except KeyError:
        generation = 0
    application = request.validated['application']
    version = request.validated['version']
    pattern = request.validated['pattern']
    service = get_service_name(application, version)
    client_state = request.validated['client-state']

    with metrics_timer('tokenserver.backend.get_user', request):
        user = backend.get_user(service, email)
    if not user:
        allowed = settings.get('tokenserver.allow_new_users', True)
        if not allowed:
            raise _unauthorized('new-users-disabled')
        with metrics_timer('tokenserver.backend.allocate_user', request):
            user = backend.allocate_user(service, email, generation,
                                         client_state)

    # Update if this client is ahead of previously-seen clients.
    updates = {}
    if generation > user['generation']:
        updates['generation'] = generation
    if client_state != user['client_state']:
        # Don't revert from some-client-state to no-client-state.
        if not client_state:
            raise _invalid_client_state('empty string')
        # Don't revert to a previous client-state.
        if client_state in user['old_client_states']:
            raise _invalid_client_state('stale value')
        # If the IdP has been sending generation numbers, then
        # don't update client-state without a change in generation number.
        if user['generation'] > 0 and 'generation' not in updates:
            raise _invalid_client_state('new value with no generation change')
        updates['client_state'] = client_state
    if updates:
        with metrics_timer('tokenserver.backend.update_user', request):
            backend.update_user(service, user, **updates)

    # Error out if this client is behind some previously-seen client.
    # This is done after the updates because some other, even more up-to-date
    # client may have raced with a concurrent update.
    if user['generation'] > generation:
        raise _unauthorized("invalid-generation")

    secrets = settings['tokenserver.secrets']
    node_secrets = secrets.get(user['node'])
    if not node_secrets:
        raise Exception("The specified node does not have any shared secret")
    secret = node_secrets[-1]  # the last one is the most recent one

    # Clients can request a smaller token duration via an undocumented
    # query parameter, for testing purposes.
    token_duration = settings.get(
        'tokenserver.token_duration', DEFAULT_TOKEN_DURATION
    )
    try:
        requested_duration = int(request.params["duration"])
    except (KeyError, ValueError):
        pass
    else:
        if 0 < requested_duration < token_duration:
            token_duration = requested_duration

    token_data = {
        'uid': user['uid'],
        'node': user['node'],
        'expires': int(time.time()) + token_duration,
        'fxa_uid': request.validated['fxa_uid'],
        'device_id': request.validated['device_id']
    }
    token = tokenlib.make_token(token_data, secret=secret)
    secret = tokenlib.get_derived_secret(token, secret=secret)

    endpoint = pattern.format(
        uid=user['uid'],
        service=service,
        node=user['node']
    )

    # To help measure user retention, include the timestamp at which we
    # first saw this user as part of the logs.
    request.metrics['uid.first_seen_at'] = user['first_seen_at']

    return {
        'id': token,
        'key': secret,
        'uid': user['uid'],
        'hashed_fxa_uid': request.validated['fxa_uid'],
        'api_endpoint': endpoint,
        'duration': token_duration,
        'hashalg': tokenlib.DEFAULT_HASHMOD
    }
 def _get_credentials(self, **data):
     id = tokenlib.make_token(data)
     key = tokenlib.get_token_secret(id)
     return {"id": id, "key": key}
Example #43
0
def return_token(request):
    """This service does the following process:

    - validates the BrowserID or OAuth credentials provided in the
      Authorization header
    - allocates when necessary a node to the user for the required service
    - checks generation number, key-rotation timestamp and x-client-state
      header for consistency
    - returns a JSON mapping containing the following values:

        - **id** -- a signed authorization token, containing the
          user's id for hthe application and the node.
        - **secret** -- a secret derived from the shared secret
        - **uid** -- the user id for this service
        - **api_endpoint** -- the root URL for the user for the service.
    """
    # at this stage, we are sure that the credentials, application and version
    # number were valid, so let's build the authentication token and return it.
    backend = request.registry.getUtility(INodeAssignment)
    settings = request.registry.settings
    email = request.validated['authorization']['email']

    # The `generation` and `keys_changed_at` fields are both optional.
    try:
        idp_claims = request.validated['authorization']['idpClaims']
    except KeyError:
        generation = 0
        keys_changed_at = 0
    else:
        generation = idp_claims.get('fxa-generation', 0)
        if not isinstance(generation, (int, long)):
            raise _unauthorized("invalid-generation")
        keys_changed_at = idp_claims.get('fxa-keysChangedAt', 0)
        if not isinstance(keys_changed_at, (int, long)):
            raise _unauthorized("invalid-credentials",
                                description="invalid keysChangedAt")

    application = request.validated['application']
    version = request.validated['version']
    pattern = request.validated['pattern']
    service = get_service_name(application, version)
    client_state = request.validated['client-state']

    with metrics_timer('tokenserver.backend.get_user', request):
        user = backend.get_user(service, email)
    if not user:
        allowed = settings.get('tokenserver.allow_new_users', True)
        if not allowed:
            raise _unauthorized('new-users-disabled')
        with metrics_timer('tokenserver.backend.allocate_user', request):
            user = backend.allocate_user(service,
                                         email,
                                         generation,
                                         client_state,
                                         keys_changed_at=keys_changed_at)

    # We now perform an elaborate set of consistency checks on the
    # provided claims, which we expect to behave as follows:
    #
    #   * `generation` is a monotonic timestamp, and increases every time
    #     there is an authentication-related change on the user's account.
    #
    #   * `keys_changed_at` is a monotonic timestamp, and increases every time
    #     the user's keys change. This is a type of auth-related change, so
    #     `keys_changed_at` <= `generation` at all times.
    #
    #   * `client_state` is a key fingerprint and should never change back
    #      to a previously-seen value.
    #
    # Callers who provide identity claims that violate any of these rules
    # either have stale credetials (in which case they should re-authenticate)
    # or are buggy (in which case we deny them access to the user's data).
    #
    # The logic here is slightly complicated by the fact that older versions
    # of the FxA server may not have been sending all the expected fields, and
    # that some clients do not report the `generation` timestamp.

    # Update if this client is ahead of previously-seen clients.
    updates = {}
    if generation > user['generation']:
        updates['generation'] = generation
    if keys_changed_at > user['keys_changed_at']:
        # If the caller reports a generation number, then a change
        # in keys should correspond to a change in generation number.
        # Unfortunately a previous version of the server that didn't
        # have `keys_changed_at` support may have already seen and
        # written the new value of `generation`. The best we can do
        # here is enforce that `keys_changed_at` <= `generation`.
        if generation > 0 and generation < keys_changed_at:
            raise _unauthorized('invalid-keysChangedAt')
        if generation == 0 and keys_changed_at > user['generation']:
            updates['generation'] = keys_changed_at
        updates['keys_changed_at'] = keys_changed_at
    if client_state != user['client_state']:
        # Don't revert from some-client-state to no-client-state.
        if not client_state:
            raise _invalid_client_state('empty string')
        # Don't revert to a previous client-state.
        if client_state in user['old_client_states']:
            raise _invalid_client_state('stale value')
        # If we have a generation number, then
        # don't update client-state without a change in generation number.
        if generation > 0 and 'generation' not in updates:
            raise _invalid_client_state('new value with no generation change')
        # If the IdP has been sending keys_changed_at timestamps, then
        # don't update client-state without a change in keys_changed_at.
        if user['keys_changed_at'] > 0 and 'keys_changed_at' not in updates:
            raise _invalid_client_state(
                'new value with no keys_changed_at change')
        updates['client_state'] = client_state
    if updates:
        with metrics_timer('tokenserver.backend.update_user', request):
            backend.update_user(service, user, **updates)

    # Error out if this client provided a generation number, but it is behind
    # the generation number of some previously-seen client.
    if generation > 0 and user['generation'] > generation:
        raise _unauthorized("invalid-generation")

    # Error out if we previously saw a keys_changed_at for this user, but they
    # haven't provided one or it's earlier than previously seen. This means
    # that once the IdP starts sending keys_changed_at, we'll error out if it
    # stops (because we can't generate a proper `fxa_kid` in this case).
    if user['keys_changed_at'] > 0:
        if user['keys_changed_at'] > keys_changed_at:
            raise _unauthorized("invalid-keysChangedAt")

    secrets = settings['tokenserver.secrets']
    node_secrets = secrets.get(user['node'])
    if not node_secrets:
        raise Exception("The specified node does not have any shared secret")
    secret = node_secrets[-1]  # the last one is the most recent one

    # Clients can request a smaller token duration via an undocumented
    # query parameter, for testing purposes.
    token_duration = settings.get('tokenserver.token_duration',
                                  DEFAULT_TOKEN_DURATION)
    try:
        requested_duration = int(request.params["duration"])
    except (KeyError, ValueError):
        pass
    else:
        if 0 < requested_duration < token_duration:
            token_duration = requested_duration

    token_data = {
        'uid':
        user['uid'],
        'node':
        user['node'],
        'expires':
        int(time.time()) + token_duration,
        'fxa_uid':
        request.validated['fxa_uid'],
        'fxa_kid':
        format_key_id(
            # Follow FxA behaviour of using generation as a fallback.
            user['keys_changed_at'] or user['generation'],
            client_state.decode('hex')),
        'hashed_fxa_uid':
        request.validated['hashed_fxa_uid'],
        'hashed_device_id':
        request.validated['hashed_device_id']
    }
    token = tokenlib.make_token(token_data, secret=secret)
    secret = tokenlib.get_derived_secret(token, secret=secret)

    endpoint = pattern.format(uid=user['uid'],
                              service=service,
                              node=user['node'])

    # To help measure user retention, include the timestamp at which we
    # first saw this user as part of the logs.
    request.metrics['uid.first_seen_at'] = user['first_seen_at']

    # To help segmented analysis of client-side metrics, we can tell
    # clients to tag their metrics with a "node type" string that is
    # at much coarser granularity than the individual node name.
    try:
        node_type = settings['tokenserver.node_type_classifier'](user['node'])
    except KeyError:
        node_type = None
    request.metrics['node_type'] = node_type

    return {
        'id': token,
        'key': secret,
        'uid': user['uid'],
        'api_endpoint': endpoint,
        'duration': token_duration,
        'hashalg': tokenlib.DEFAULT_HASHMOD,
        # Extra stuff for clients to include in telemetry.
        'hashed_fxa_uid': request.validated['hashed_fxa_uid'],
        'node_type': node_type,
    }
Example #44
0
 def test_tokens_are_native_string_type(self):
     token = tokenlib.make_token({"hello": "world"})
     assert isinstance(token, str)
 def get_token(user_id):
     return tokenlib.make_token({'user_id': user_id}, secret='h5j43hl254jl8l7k68')
Example #46
0
 def test_that_macauth_can_use_per_node_hostname_secrets(self):
     with tempfile.NamedTemporaryFile() as sf:
         # Write some secrets to a file.
         sf.write("http://host1.com,0001:secret11,0002:secret12\n")
         sf.write("https://host2.com,0001:secret21,0002:secret22\n")
         sf.write("https://host3.com:444,0001:secret31,0002:secret32\n")
         sf.flush()
         # Configure the plugin to load them.
         config2 = pyramid.testing.setUp()
         config2.add_settings(DEFAULT_SETTINGS)
         config2.add_settings({
             "macauth.secrets_file": sf.name,
         })
         config2.include("mozsvc.user")
         config2.commit()
         # It should accept a request signed with the old secret on host1.
         req = self.make_request(config=config2, environ={
             "HTTP_HOST": "host1.com",
         })
         id = tokenlib.make_token({"uid": 42}, secret="secret11")
         key = tokenlib.get_token_secret(id, secret="secret11")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request signed with the new secret on host1.
         req = self.make_request(config=config2, environ={
             "HTTP_HOST": "host1.com",
         })
         id = tokenlib.make_token({"uid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should reject a request signed with secret from other host.
         req = self.make_request(config=config2, environ={
             "HTTP_HOST": "host2.com",
         })
         id = tokenlib.make_token({"uid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(HTTPUnauthorized, authenticated_userid, req)
         # It should reject a request over plain http when host2 is ssl.
         req = self.make_request(config=config2, environ={
             "HTTP_HOST": "host2.com",
         })
         id = tokenlib.make_token({"uid": 42}, secret="secret22")
         key = tokenlib.get_token_secret(id, secret="secret22")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(HTTPUnauthorized, authenticated_userid, req)
         # It should accept a request signed with the new secret on host2.
         req = self.make_request(config=config2, environ={
             "HTTP_HOST": "host2.com",
             "wsgi.url_scheme": "https",
         })
         id = tokenlib.make_token({"uid": 42}, secret="secret22")
         key = tokenlib.get_token_secret(id, secret="secret22")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request to host1 with an explicit port number.
         # Use some trickery to give host_url a value with default port.
         req = ExpandoRequest(self.make_request(config=config2, environ={
             "HTTP_HOST": "host1.com:80",
             "wsgi.url_scheme": "http",
         }))
         req.host_url = "http://host1.com:80"
         id = tokenlib.make_token({"uid": 42}, secret="secret11")
         key = tokenlib.get_token_secret(id, secret="secret11")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request to host2 with an explicit port number.
         # Use some trickery to give host_url a value with default port.
         req = ExpandoRequest(self.make_request(config=config2, environ={
             "HTTP_HOST": "host2.com:443",
             "wsgi.url_scheme": "https",
         }))
         req.host_url = "https://host2.com:443"
         id = tokenlib.make_token({"uid": 42}, secret="secret22")
         key = tokenlib.get_token_secret(id, secret="secret22")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request to host3 on a custom port.
         req = self.make_request(config=config2, environ={
             "HTTP_HOST": "host3.com:444",
             "wsgi.url_scheme": "https",
         })
         id = tokenlib.make_token({"uid": 42}, secret="secret32")
         key = tokenlib.get_token_secret(id, secret="secret32")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should reject unknown hostnames.
         req = self.make_request(config=config2, environ={
             "HTTP_HOST": "host4.com",
         })
         id = tokenlib.make_token({"uid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(HTTPUnauthorized, authenticated_userid, req)
 def _get_credentials(self, **data):
     id = tokenlib.make_token(data)
     key = tokenlib.get_token_secret(id)
     return {"id": id, "key": key}
Example #48
0
    def generate(self):
        """Pick an identity, log in and generate the auth token."""
        # If the server_url has a hash fragment, it's a storage node and
        # that's the secret.  Otherwise it's a token server url.
        uid = random.randint(1, 1000000)
        url = urlparse(self.server_url)
        if url.fragment:
            endpoint = url._replace(fragment="", path="/1.5/" + str(uid))
            self.endpoint_url = urlunparse(endpoint)
            data = {
                "uid": uid,
                "node": urlunparse(url._replace(fragment="")),
                "expires": time.time() + ASSERTION_LIFETIME,
            }
            self.auth_token = make_token(data, secret=url.fragment)
            self.auth_secret = derive(self.auth_token, secret=url.fragment)
        else:
            email = "user%s@%s" % (uid, MOCKMYID_DOMAIN)
            exp = time.time() + ASSERTION_LIFETIME + self.timeskew
            assertion = browserid.tests.support.make_assertion(
                email=email,
                audience=self.server_url,
                issuer=MOCKMYID_DOMAIN,
                issuer_keypair=(None, MOCKMYID_PRIVATE_KEY),
                exp=int(exp * 1000),
            )
            token_url = self.server_url + "/1.0/sync/1.5"
            response = json_request(token_url,
                                    headers={
                                        "Authorization":
                                        "BrowserID " + assertion,
                                    })
            # Maybe timeskew between client and server?
            if response['status'] == 401:
                server_time = int(response['headers']["X-Timestamp"])
                self.timeskew = server_time - int(time.time())
                exp = time.time() + ASSERTION_LIFETIME + self.timeskew
                assertion = browserid.tests.support.make_assertion(
                    email=email,
                    audience=self.server_url,
                    issuer=MOCKMYID_DOMAIN,
                    issuer_keypair=(None, MOCKMYID_PRIVATE_KEY),
                    exp=int(exp * 1000),
                )
                response = json_request(token_url,
                                        headers={
                                            "Authorization":
                                            "BrowserID " + assertion,
                                        })

            if response['status'] > 299:
                raise ValueError(response['status'])

            credentials = response['content']
            self.auth_token = credentials["id"].encode('ascii')
            self.auth_secret = credentials["key"].encode('ascii')
            self.endpoint_url = credentials["api_endpoint"]

        url = urlparse(self.endpoint_url)
        self.endpoint_scheme = url.scheme
        self.endpoint_path = url.path
        if ':' in url.netloc:
            self.endpoint_host, self.endpoint_port = url.netloc.rsplit(":", 1)
        else:
            self.endpoint_host = url.netloc
            if url.scheme == "http":
                self.endpoint_port = "80"
            else:
                self.endpoint_port = "443"
Example #49
0
def return_token(request):
    """This service does the following process:

    - validates the Browser-ID assertion provided on the Authorization header
    - allocates when necessary a node to the user for the required service
    - deals with the X-Conditions-Accepted header
    - returns a JSON mapping containing the following values:

        - **id** -- a signed authorization token, containing the
          user's id for hthe application and the node.
        - **secret** -- a secret derived from the shared secret
        - **uid** -- the user id for this servic
        - **api_endpoint** -- the root URL for the user for the service.
    """
    # at this stage, we are sure that the assertion, application and version
    # number were valid, so let's build the authentication token and return it.
    backend = request.registry.getUtility(INodeAssignment)
    email = request.validated['assertion']['email']
    application = request.validated['application']
    version = request.validated['version']
    pattern = request.validated['pattern']
    service = get_service_name(application, version)
    accepted = request.validated['x-conditions-accepted']

    # get the node or allocate one if none is already set
    uid, node, to_accept = backend.get_node(email, service)
    if to_accept is not None:
        # the backend sent a tos url, meaning the user needs to
        # sign it, we want to compare both tos and raise a 403
        # if they are not equal
        if not accepted:
            to_accept = dict([(name, value) for name, value, __ in to_accept])
            raise json_error(403, location='header',
                            description='Need to accept conditions',
                            name='X-Conditions-Accepted',
                            condition_urls=to_accept)
    # at this point, either the tos were signed or the service does not
    # have any ToS
    if node is None or uid is None:
        metlog = request.registry['metlog']
        start = time.time()
        try:
            uid, node = backend.allocate_node(email, service)
        finally:
            duration = time.time() - start
            metlog.timer_send("token.sql.allocate_node", duration)

    secrets = request.registry.settings['tokenserver.secrets_file']
    node_secrets = secrets.get(node)
    if not node_secrets:
        raise Exception("The specified node does not have any shared secret")
    secret = node_secrets[-1]  # the last one is the most recent one

    token_duration = request.registry.settings.get(
            'tokenserver.token_duration', DEFAULT_TOKEN_DURATION)

    token = make_token({'uid': uid, 'service_entry': node},
            timeout=token_duration, secret=secret)
    # XXX needs to be renamed as 'get_derived_secret' because
    # it's not clear here it's a derived
    secret = get_token_secret(token, secret=secret)

    api_endpoint = pattern.format(uid=uid, service=service, node=node)

    # FIXME add the algo used to generate the token
    return {'id': token, 'key': secret, 'uid': uid,
            'api_endpoint': api_endpoint, 'duration': token_duration}
Example #50
0
def return_token(request):
    """This service does the following process:

    - validates the BrowserID assertion provided on the Authorization header
    - allocates when necessary a node to the user for the required service
    - checks generation numbers and x-client-state header
    - returns a JSON mapping containing the following values:

        - **id** -- a signed authorization token, containing the
          user's id for hthe application and the node.
        - **secret** -- a secret derived from the shared secret
        - **uid** -- the user id for this servic
        - **api_endpoint** -- the root URL for the user for the service.
    """
    # at this stage, we are sure that the assertion, application and version
    # number were valid, so let's build the authentication token and return it.
    backend = request.registry.getUtility(INodeAssignment)
    settings = request.registry.settings
    email = request.validated['assertion']['email']
    try:
        idp_claims = request.validated['assertion']['idpClaims']
        generation = idp_claims['fxa-generation']
        if not isinstance(generation, (int, long)):
            raise _unauthorized("invalid-generation")
    except KeyError:
        generation = 0
    application = request.validated['application']
    version = request.validated['version']
    pattern = request.validated['pattern']
    service = get_service_name(application, version)
    client_state = request.validated['client-state']

    with metrics_timer('tokenserver.backend.get_user', request):
        user = backend.get_user(service, email)
    if not user:
        allowed = settings.get('tokenserver.allow_new_users', True)
        if not allowed:
            raise _unauthorized('invalid-credentials')
        with metrics_timer('tokenserver.backend.allocate_user', request):
            user = backend.allocate_user(service, email, generation,
                                         client_state)

    # Update if this client is ahead of previously-seen clients.
    updates = {}
    if generation > user['generation']:
        updates['generation'] = generation
    if client_state != user['client_state']:
        # Don't revert from some-client-state to no-client-state.
        if not client_state:
            raise _unauthorized('invalid-client-state')
        # Don't revert to a previous client-state.
        if client_state in user['old_client_states']:
            raise _unauthorized('invalid-client-state')
        # If the IdP has been sending generation numbers, then
        # don't update client-state without a change in generation number.
        if user['generation'] > 0 and 'generation' not in updates:
            raise _unauthorized('invalid-client-state')
        updates['client_state'] = client_state
    if updates:
        with metrics_timer('tokenserver.backend.update_user', request):
            backend.update_user(service, user, **updates)

    # Error out if this client is behind some previously-seen client.
    # This is done after the updates because some other, even more up-to-date
    # client may have raced with a concurrent update.
    if user['generation'] > generation:
        raise _unauthorized("invalid-generation")

    secrets = settings['tokenserver.secrets']
    node_secrets = secrets.get(user['node'])
    if not node_secrets:
        raise Exception("The specified node does not have any shared secret")
    secret = node_secrets[-1]  # the last one is the most recent one

    token_duration = settings.get(
        'tokenserver.token_duration', DEFAULT_TOKEN_DURATION
    )
    try:
        requested_duration = int(request.params["duration"])
    except (KeyError, ValueError):
        pass
    else:
        if 0 < requested_duration < token_duration:
            token_duration = requested_duration

    token_data = {
        'uid': user['uid'],
        'node': user['node'],
        'expires': int(time.time()) + token_duration,
    }
    token = tokenlib.make_token(token_data, secret=secret)
    secret = tokenlib.get_derived_secret(token, secret=secret)

    endpoint = pattern.format(
        uid=user['uid'],
        service=service,
        node=user['node']
    )

    return {'id': token, 'key': secret, 'uid': user['uid'],
            'api_endpoint': endpoint, 'duration': token_duration,
            'hashalg': tokenlib.DEFAULT_HASHMOD}
Example #51
0
 def test_that_macauth_can_use_per_node_hostname_secrets(self):
     with tempfile.NamedTemporaryFile() as sf:
         # Write some secrets to a file.
         sf.write("http://host1.com,0001:secret11,0002:secret12\n")
         sf.write("https://host2.com,0001:secret21,0002:secret22\n")
         sf.write("https://host3.com:444,0001:secret31,0002:secret32\n")
         sf.flush()
         # Configure the plugin to load them.
         config2 = pyramid.testing.setUp()
         config2.add_settings(DEFAULT_SETTINGS)
         config2.add_settings({
             "macauth.secrets_file": sf.name,
         })
         config2.include("mozsvc.user")
         config2.commit()
         # It should accept a request signed with the old secret on host1.
         req = self.make_request(config=config2,
                                 environ={
                                     "HTTP_HOST": "host1.com",
                                 })
         id = tokenlib.make_token({"uid": 42}, secret="secret11")
         key = tokenlib.get_token_secret(id, secret="secret11")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request signed with the new secret on host1.
         req = self.make_request(config=config2,
                                 environ={
                                     "HTTP_HOST": "host1.com",
                                 })
         id = tokenlib.make_token({"uid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should reject a request signed with secret from other host.
         req = self.make_request(config=config2,
                                 environ={
                                     "HTTP_HOST": "host2.com",
                                 })
         id = tokenlib.make_token({"uid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(HTTPUnauthorized, authenticated_userid, req)
         # It should reject a request over plain http when host2 is ssl.
         req = self.make_request(config=config2,
                                 environ={
                                     "HTTP_HOST": "host2.com",
                                 })
         id = tokenlib.make_token({"uid": 42}, secret="secret22")
         key = tokenlib.get_token_secret(id, secret="secret22")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(HTTPUnauthorized, authenticated_userid, req)
         # It should accept a request signed with the new secret on host2.
         req = self.make_request(config=config2,
                                 environ={
                                     "HTTP_HOST": "host2.com",
                                     "wsgi.url_scheme": "https",
                                 })
         id = tokenlib.make_token({"uid": 42}, secret="secret22")
         key = tokenlib.get_token_secret(id, secret="secret22")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request to host1 with an explicit port number.
         # Use some trickery to give host_url a value with default port.
         req = ExpandoRequest(
             self.make_request(config=config2,
                               environ={
                                   "HTTP_HOST": "host1.com:80",
                                   "wsgi.url_scheme": "http",
                               }))
         req.host_url = "http://host1.com:80"
         id = tokenlib.make_token({"uid": 42}, secret="secret11")
         key = tokenlib.get_token_secret(id, secret="secret11")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request to host2 with an explicit port number.
         # Use some trickery to give host_url a value with default port.
         req = ExpandoRequest(
             self.make_request(config=config2,
                               environ={
                                   "HTTP_HOST": "host2.com:443",
                                   "wsgi.url_scheme": "https",
                               }))
         req.host_url = "https://host2.com:443"
         id = tokenlib.make_token({"uid": 42}, secret="secret22")
         key = tokenlib.get_token_secret(id, secret="secret22")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should accept a request to host3 on a custom port.
         req = self.make_request(config=config2,
                                 environ={
                                     "HTTP_HOST": "host3.com:444",
                                     "wsgi.url_scheme": "https",
                                 })
         id = tokenlib.make_token({"uid": 42}, secret="secret32")
         key = tokenlib.get_token_secret(id, secret="secret32")
         macauthlib.sign_request(req, id, key)
         self.assertEquals(authenticated_userid(req), 42)
         # It should reject unknown hostnames.
         req = self.make_request(config=config2,
                                 environ={
                                     "HTTP_HOST": "host4.com",
                                 })
         id = tokenlib.make_token({"uid": 42}, secret="secret12")
         key = tokenlib.get_token_secret(id, secret="secret12")
         macauthlib.sign_request(req, id, key)
         self.assertRaises(HTTPUnauthorized, authenticated_userid, req)