| 1 | --- |
| 2 | title: Authentication and authorization |
| 3 | description: Use native Effect HTTP middleware and ordinary application effects to authorize Git operations. |
| 4 | --- |
| 5 | |
| 6 | Your application owns users, credentials, and authorization. Git's binary protocol |
| 7 | runs over HTTP, so native Effect API middleware also applies to push and fetch. |
| 8 | |
| 9 | ## Provide the request's user |
| 10 | |
| 11 | ```typescript |
| 12 | class Authentication extends HttpApiMiddleware.Service< |
| 13 | Authentication, |
| 14 | { provides: CurrentUser } |
| 15 | >()("app/Authentication", { error: Unauthorized }) {} |
| 16 | |
| 17 | class AppApi extends HttpApi.make("app") |
| 18 | .addHttpApi(Git.Api) |
| 19 | .middleware(Authentication) {} |
| 20 | ``` |
| 21 | |
| 22 | Supply `Authentication` with an ordinary layer. Its implementation resolves a |
| 23 | credential and provides `CurrentUser` while running the endpoint effect. Build |
| 24 | Git groups with `HttpApiBuilder.group(AppApi, ...)`, so their endpoint metadata |
| 25 | includes this middleware. The [complete example](https://github.com/alchemy-run/alchemy/tree/main/examples/cloudflare-git-service/src/api/middleware.ts) |
| 26 | uses Better Auth sessions and API keys this way. |
| 27 | |
| 28 | `handleRaw` skips automatic payload decoding; it still runs API middleware. |
| 29 | Your custom push handler can yield the same user and database services as a JSON |
| 30 | handler. [Engine operations](/git/blocks/engine) shows the decode/prepare/commit flow. |
| 31 | |
| 32 | ## Authorize proposed changes |
| 33 | |
| 34 | Middleware can authorize repository access before reading a pack. Once the |
| 35 | handler decodes ref commands, call application policy functions. After preparing |
| 36 | a push, validate its staged objects. Only then commit. |
| 37 | |
| 38 | | Boundary | Application decision | |
| 39 | | --- | --- | |
| 40 | | Before decoding | May this caller read or write this repository? | |
| 41 | | After decoding commands | May these refs be created, moved, or deleted? | |
| 42 | | After preparing objects | Are the incoming commits and files acceptable? | |
| 43 | |
| 44 | Policies can use typed errors and services. They are ordinary Effects, split into |
| 45 | modules and called in sequence. Apply shared write policies to push, REST ref |
| 46 | updates/deletions, and REST/GitHub pull merges; authorizing one endpoint does not |
| 47 | authorize or protect the others. |
| 48 | |
| 49 | ## Git credentials and public repositories |
| 50 | |
| 51 | Git sends HTTP Basic with the credential in the password field. |
| 52 | `HttpApiBuilder.securityDecode(HttpApiSecurity.basic)` reads it. Return a `401` |
| 53 | with `WWW-Authenticate: Basic realm="git"` when credentials are needed. |
| 54 | |
| 55 | `Git.isRead(request)` recognizes REST reads, upload-pack, and fetch advertisements. |
| 56 | Receive-pack advertisements are writes. Resolve the repository before allowing |
| 57 | anonymous reads, according to your application's public-repository policy. |
| 58 | |
| 59 | ## Router middleware is also supported |
| 60 | |
| 61 | The tutorial introduces `HttpRouter.middleware` first. It can provide a typed |
| 62 | `Session` service across both Git and application routes: |
| 63 | |
| 64 | ```typescript |
| 65 | const PublicRoutes = Layer.mergeAll(AppApiLive, Git.ApiLive).pipe( |
| 66 | Layer.provide(Authentication.layer), |
| 67 | ); |
| 68 | ``` |
| 69 | |
| 70 | This `Authentication` is the tutorial's router middleware descriptor. Router |
| 71 | middleware does not add error schemas to `Git.Api`. Declare application errors |
| 72 | on your API when clients need to decode them. Native API middleware, as in the |
| 73 | first example, carries both its provided services and its error schemas. |
| 74 | |
| 75 | ## Internal hashing |
| 76 | |
| 77 | Mount `Git.InternalApiLive` outside application authentication. Its handler |
| 78 | checks its own internal secret; user credentials do not authorize internal hashing. |