Authentication
OAuth2 Integration
Section titled “OAuth2 Integration”Crate integrates with vibe.d’s OAuth2 authenticator. Call enable() on the router to add token validation to all routes:
import vibeauth.authenticators.OAuth2;
auto crateRouter = router.crateSetup!RestApi;
auto oauth = new OAuth2(/* config */);crateRouter.enable(oauth);
crateRouter.add(userCrate);crateRouter.add(productCrate);The enable() method registers OAuth2 token validation middleware on the vibe.d URLRouter before Crate’s handler. Every request is validated before reaching any Crate operation.
Auth Middleware Patterns
Section titled “Auth Middleware Patterns”In practice, different endpoints need different access levels. Rather than a single global auth check, Crate applications use middleware classes that implement specific access patterns.
Public Data Middleware
Section titled “Public Data Middleware”Allows unauthenticated GET requests but requires auth for writes:
class PublicDataMiddleware { @getList @getItem void readAccess(HTTPServerRequest req, HTTPServerResponse res) @safe { // No authentication required for reading }
@create @replace @patch @delete_ void writeAccess(HTTPServerRequest req, HTTPServerResponse res) @safe { enforceAuthenticated(req, res); }}Private Data Middleware
Section titled “Private Data Middleware”Requires authentication for all operations:
class PrivateDataMiddleware { @any void any(HTTPServerRequest req, HTTPServerResponse res) @safe { enforceAuthenticated(req, res); }}Contribution Middleware
Section titled “Contribution Middleware”Requires authentication and verifies the user has contributor rights:
class ContributionMiddleware { @any void any(HTTPServerRequest req, HTTPServerResponse res) @safe { enforceAuthenticated(req, res); enforceContributor(req, res); }}Applying Auth Per Model
Section titled “Applying Auth Per Model”Different models can have different auth requirements:
auto auth = new AuthMiddlewareFactory(/* config */);
// Public read, authenticated writecrateRouter .prepare(articleCrate) .and(auth.publicDataMiddleware);
// Fully privatecrateRouter .prepare(settingsCrate) .and(auth.privateDataMiddleware);
// Contributor-onlycrateRouter .prepare(issueCrate) .and(auth.contributionMiddleware);User Data Middleware
Section titled “User Data Middleware”A common pattern is injecting the authenticated user’s data into the request context:
class UserDataMiddleware { @any void any(HTTPServerRequest req, HTTPServerResponse res) @safe { if (auto user = getAuthenticatedUser(req)) { // Make user data available to downstream middleware req.params["userId"] = user.id; req.params["userRole"] = user.role; } }}Then downstream middleware can use req.params["userId"] to filter data by ownership.
Admin Request Middleware
Section titled “Admin Request Middleware”Check if the current user has admin privileges:
class AdminRequestMiddleware { @any void any(HTTPServerRequest req, HTTPServerResponse res) @safe { auto userId = req.params.get("userId", ""); if (userId.length > 0 && isAdmin(userId)) { req.params["isAdmin"] = "true"; } }}Model References and crateGetters
Section titled “Model References and crateGetters”When a model references another model, Crate needs to look up the referenced item during POST/PATCH operations. This is done via crateGetters:
// Register getters for all referenced modelscrateGetters["Team"] = &teamCrate.getItem;crateGetters["Picture"] = &pictureCrate.getItem;
// Now Campaign (which references Team and Picture) can resolve referencescrateRouter.add(campaignCrate);If you forget to register a getter, POST/PATCH requests will fail with a 500 error: “no getter for Team model”.
Every model that uses Visibility (which references Team and Picture) needs at minimum:
crateGetters["Team"] = &teamCrate.getItem;crateGetters["Picture"] = &pictureCrate.getItem;Next Steps
Section titled “Next Steps”- Learn about multi-protocol support for serving REST, MCP, and GraphQL