diff --git a/src/_secureaccesstokenauthorizer/__init__.py b/src/_secureaccesstokenauthorizer/__init__.py
index 4990b680dc807e489646b6ae427a5e4973214bd0..51b6aadfbd94abea8e8d96e67e989f05d6202888 100644
--- a/src/_secureaccesstokenauthorizer/__init__.py
+++ b/src/_secureaccesstokenauthorizer/__init__.py
@@ -13,3 +13,11 @@
 # limitations under the License.
 
 __version__ = "0.0"
+
+from ._storage_server import (
+    SecureAccessTokenAuthorizerStorageServer,
+)
+
+from ._plugin import (
+    SecureAccessTokenAuthorizer,
+)
diff --git a/src/_secureaccesstokenauthorizer/_plugin.py b/src/_secureaccesstokenauthorizer/_plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..57a8286a33c7fd27032fa804966a44ef7db71809
--- /dev/null
+++ b/src/_secureaccesstokenauthorizer/_plugin.py
@@ -0,0 +1,47 @@
+# Copyright 2019 PrivateStorage.io, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+The Twisted plugin that glues the Secure Access Token system into
+Tahoe-LAFS.
+"""
+
+from zope.interface import (
+    implementer,
+)
+
+from allmydata.interfaces import (
+    IFoolscapStoragePlugin,
+)
+
+from . import (
+    SecureAccessTokenAuthorizerStorageServer,
+)
+
+@implementer(IFoolscapStoragePlugin)
+class SecureAccessTokenAuthorizer(object):
+    """
+    A storage plugin which provides a token-based access control mechanism on
+    top of the Tahoe-LAFS built-in storage server interface.
+    """
+    name = u"privatestorageio-satauthz-v1"
+
+    def get_storage_server(self, configuration, get_anonymous_storage_server):
+        return SecureAccessTokenAuthorizerStorageServer(
+            get_anonymous_storage_server(),
+            **configuration,
+        )
+
+    def get_storage_client(self, configuration, announcement):
+        raise NotImplementedError()
diff --git a/src/_secureaccesstokenauthorizer/_storage_server.py b/src/_secureaccesstokenauthorizer/_storage_server.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa5032f5e2a3e541248fe98f8a14a92ca55dc17f
--- /dev/null
+++ b/src/_secureaccesstokenauthorizer/_storage_server.py
@@ -0,0 +1,86 @@
+# Copyright 2019 PrivateStorage.io, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+A Tahoe-LAFS RIStorageServer-alike which authorizes writes and lease
+updates using a per-call token.
+"""
+
+from allmydata.interfaces import (
+    RIStorageServer,
+)
+
+MAXIMUM_TOKENS_PER_CALL = 10
+TOKEN_LENGTH = 97
+
+Token = ByteStringConstraint(maxLength=TOKEN_LENGTH, minLength=TOKEN_LENGTH)
+TokenList = ListOf(Token, maxLength=MAXIMUM_TOKENS_PER_CALL)
+
+
+def add_tokens(schema):
+    """
+    Add a ``tokens`` parameter to the given method schema.
+
+    :param foolscap.remoteinterface.RemoteMethodSchema schema: An existing
+        method schema to modify.
+
+    :return foolscap.remoteinterface.RemoteMethodSchema: A schema like
+        ``schema`` but with one additional required argument.
+    """
+    return add_arguments(schema, tokens=TokenList)
+
+
+
+def add_arguments(schema, **kwargs):
+    new_kwargs = dict(**zip(schema.argumentNames, schema.argConstraints))
+    new_kwargs.update(kwargs)
+    modified_schema = RemoteMethodSchema(**new_kwargs)
+    return modified_schema
+
+
+
+class RITokenAuthorizedStorageServer(RemoteInterface):
+    __remote_name__ = (
+        "RITokenAuthorizedStorageServer.tahoe.privatestorage.io"
+    )
+
+    get_version = RIStorageServer["get_version"]
+
+    allocate_buckets = add_tokens(RIStorageServer["allocate_buckets"])
+
+    add_lease = add_tokens(RIStorageServer["add_lease"])
+
+    renew_lease = add_tokens(RIStorageServer["renew_lease"])
+
+    get_buckets = RIStorageServer["get_buckets"]
+
+    slot_readv = RIStorageServer["slot_readv"]
+
+    slot_testv_and_readv_and_writev = add_tokens(
+        RIStorageServer["slot_testv_and_readv_and_writev"],
+    )
+
+    advise_corrupt_share = RIStorageServer["advise_corrupt_share"]
+
+
+
+@implementer(RITokenAuthorizedStorageServer)
+class SecureAccessTokenAuthorizerStorageServer(proxyForInterface(RIStorageServer)):
+    def allocate_buckets(self, tokens, *a, **kw):
+        self._validate_tokens(tokens)
+        return super(SecureAccessTokenAuthorizerStorageServer, self).allocate_buckets(*a, **kw)
+
+    def add_lease(self, tokens, *a, **kw):
+        self._validate_tokens(tokens)
+        return super(SecureAccessTokenAuthorizerStorageServer, self).add_lease(*a, **kw)
diff --git a/src/twisted/plugins/secureaccesstokenauthorizer.py b/src/twisted/plugins/secureaccesstokenauthorizer.py
index 4fa53c24ef8fc0a8de39a99887d180b84bb541f0..de01bbecc90c88492a69152d72c14030115eb926 100644
--- a/src/twisted/plugins/secureaccesstokenauthorizer.py
+++ b/src/twisted/plugins/secureaccesstokenauthorizer.py
@@ -15,3 +15,9 @@
 """
 A drop-in to supply plugins to the Twisted plugin system.
 """
+
+from _secureaccesstokenauthorizer import (
+    SecureAccessTokenAuthorizer,
+)
+
+storage_server = SecureAccessTokenAuthorizer()