Bearer tokens
Reboot authenticates calls with the standard
Authorization: Bearer header. When you configure
oauth=, Reboot mints those tokens and the generated
clients attach them for you, so there is nothing to do.
There are two situations in which you manage bearer tokens yourself
instead of Reboot doing it all for you: attaching a token by hand
(from a script, a server-to-server call, or a test), and accepting
tokens that come from somewhere other than Reboot's OAuth server.
This page covers both.
Attaching a token
From within your application
To carry a bearer token on every call to a particular instance,
pass it to ref():
- Python
- TypeScript
from_account = Account.ref(
request.from_account_id,
bearer_token=bearer_token,
)
const fromAccount = Account.ref(request.fromAccountId, { bearerToken });
You can also pass it as an option when doing explicit construction:
- Python
- TypeScript
bank, _ = await Bank.create(
context,
SINGLETON_BANK_ID,
Options(bearer_token=VALID_JWT),
)
const [bank] = await Bank.create(
context,
SINGLETON_BANK_ID,
{},
{ bearerToken: VALID_JWT }
);
From an ExternalContext
To carry a token on every call made from an
ExternalContext:
- Python
- TypeScript
context = ExternalContext(
name='Example',
url='http://localhost:9991',
bearer_token=token,
)
const context = new ExternalContext({
name: "Example",
url: "http://localhost:9991",
bearerToken: token,
});
From React
When you use Reboot's own sign-in, the token is handled for you:
useSignIn() establishes the session and
the provider attaches the bearer. If the token comes from somewhere
else, though, set it yourself:
import { useRebootClient } from "@reboot-dev/reboot-react";
const { setBearerToken } = useRebootClient();
setBearerToken(token);
To start out with a token you already have, pass it to
RebootClientProvider instead:
<RebootClientProvider url={url} token={token}>
<App />
</RebootClientProvider>
From initialize
An initialize function
runs with application-internal privileges by default. To have its
calls authenticated as a particular caller instead, give
Application the token to use:
- Python
- TypeScript
application = Application(
servicers=[...],
initialize=initialize,
initialize_bearer_token=os.environ.get("INITIALIZE_BEARER_TOKEN"),
)
new Application({
servicers: [...],
initialize,
initializeBearerToken: process.env.INITIALIZE_BEARER_TOKEN,
}).run();
Verifying tokens yourself
The OAuth server verifies the tokens it minted. To accept tokens
minted by something else — an existing identity provider, an API-key
scheme of your own, a legacy service — supply a TokenVerifier.
Set it on your Application:
- Python
- TypeScript
async def main():
application = Application(
servicers=[...],
token_verifier=MyTokenVerifier(...),
)
await application.run()
new Application({
servicers: [...],
...,
tokenVerifier: new MyTokenVerifier(...),
}).run();
In unit tests, hand that same Application to the test harness's
up:
- Python
- TypeScript
await self.rbt.up(
Application(
servicers=[...],
token_verifier=MyTokenVerifier(...),
)
)
await rbt.up(
new Application({
servicers: [...],
tokenVerifier: new MyTokenVerifier(...),
})
);
The interface has a single method. It receives the token from the
Authorization: Bearer header and returns an Auth object when the
token is valid:
- Python
- TypeScript
@abstractmethod
async def verify_token(
self,
context: ReaderContext,
token: Optional[str],
) -> VerifyTokenResult:
abstract verifyToken(
context: ReaderContext,
token?: string
): Promise<Auth | null>;
Set any properties you like on the returned Auth
(Python,
TypeScript)
for your authorizers to consume. The user_id
(Python) / userId (TypeScript) property is special: it is what marks
this as a valid user, and what state_id_is_user_id and the User
default compare against.
Token verification does not necessarily mean user authentication!
Depending on where and how tokens are generated, a valid token may only mean "this is a valid user of that provider" — not "this is a user of your application". Read your provider's documentation carefully, and make sure you are validating tokens in a way that is specific to your application (audience checks, issuer checks, and so on).
Combining a verifier with Reboot's OAuth
oauth= and token_verifier= can be set together. The OAuth
server's verifier runs first: a token it minted is accepted, or
rejected if it has expired; any other token is passed on to your
TokenVerifier.
Tokens your TokenVerifier accepts authenticate Reboot RPCs. They do
not authenticate the /mcp endpoint, because
MCP clients sign in through OAuth rather than presenting a bearer
token of their own, so that endpoint takes only tokens the OAuth
server minted.
Third-party identity providers without Reboot's OAuth server
If you would rather not use oauth= at all — for example because your
users already sign in through an existing system that hands your front
end an access token — the integration is:
- Implement a
TokenVerifierthat validates that provider's access tokens and producesAuthobjects with the rightuser_id. - Provide authorizer rules for your servicers.
Note that User auto-construction needs oauth=:
a token_verifier= authenticates requests but never constructs users,
so an application with a User type and no oauth= refuses to start.