# Auth Schema

**Proto file:** `proto/qpc/v1/auth.proto`
**Package:** `qpc.v1`
**Method IDs:** 100-103

The auth proto defines the OPAQUE asymmetric password-authenticated key exchange (PAKE) messages used for user registration and login. OPAQUE never transmits the password to the server; the server learns only a random value derived from the password.

Registration is a two-round-trip flow (start + finish). Login is a two-round-trip flow (start + finish). On successful login, the server returns a `session_token` used to authenticate subsequent RPCs.

See [Authentication Service Internals](../internals/authentication-service.md) for the server-side implementation and the full flow diagram.

---

## Full proto listing

```protobuf
syntax = "proto3";
package qpc.v1;

// OPAQUE registration + login (4 methods).
// Method IDs: 100-103.

message OpaqueRegisterStartRequest {
  string username = 1;
  bytes request = 2;
}

message OpaqueRegisterStartResponse {
  bytes response = 1;
}

message OpaqueRegisterFinishRequest {
  string username = 1;
  bytes upload = 2;
  bytes identity_key = 3;
}

message OpaqueRegisterFinishResponse {
  bool success = 1;
}

message OpaqueLoginStartRequest {
  string username = 1;
  bytes request = 2;
}

message OpaqueLoginStartResponse {
  bytes response = 1;
}

message OpaqueLoginFinishRequest {
  string username = 1;
  bytes finalization = 2;
  bytes identity_key = 3;
}

message OpaqueLoginFinishResponse {
  bytes session_token = 1;
}
```

---

## Registration flow (IDs 100-101)

User registration takes two round trips. The `request` and `response` fields carry opaque OPAQUE protocol blobs; their internal structure is defined by the `opaque-ke` crate.

### OpaqueRegisterStart (ID 100)

```
Client                          Server
  |                                |
  |  OpaqueRegisterStartRequest    |
  |  username: "alice"             |
  |  request: <OPAQUE blob>        |
  | -----------------------------> |
  |                                |
  |  OpaqueRegisterStartResponse   |
  |  response: <OPAQUE blob>       |
  | <----------------------------- |
```

**Request fields:**

| Field | Type | Description |
|-------|------|-------------|
| `username` | `string` | The username being registered. Must be unique on the server. |
| `request` | `bytes` | OPAQUE `RegistrationRequest` blob generated by the client using the `opaque-ke` crate. |

**Response fields:**

| Field | Type | Description |
|-------|------|-------------|
| `response` | `bytes` | OPAQUE `RegistrationResponse` blob generated by the server. Client feeds this into the finish step. |

### OpaqueRegisterFinish (ID 101)

```
Client                          Server
  |                                |
  |  OpaqueRegisterFinishRequest   |
  |  username: "alice"             |
  |  upload: <OPAQUE record>       |
  |  identity_key: <32 bytes>      |
  | -----------------------------> |
  |                                |
  |  OpaqueRegisterFinishResponse  |
  |  success: true                 |
  | <----------------------------- |
```

**Request fields:**

| Field | Type | Description |
|-------|------|-------------|
| `username` | `string` | Must match the username from the start request. |
| `upload` | `bytes` | OPAQUE `RegistrationUpload` blob. The server stores this as the user's OPAQUE record; it contains the password-derived key material without revealing the password. |
| `identity_key` | `bytes` | The user's Ed25519 identity public key (32 bytes). Stored alongside the OPAQUE record and used as the user's long-term identifier for key packages and delivery queues. |

**Response fields:**

| Field | Type | Description |
|-------|------|-------------|
| `success` | `bool` | `true` if the registration record was stored successfully. `false` if the username is already taken or another error occurred. |

---

## Login flow (IDs 102-103)

User login also takes two round trips. On success, the server issues a `session_token` that the client attaches to subsequent authenticated RPCs.

### OpaqueLoginStart (ID 102)

```
Client                          Server
  |                                |
  |  OpaqueLoginStartRequest       |
  |  username: "alice"             |
  |  request: <OPAQUE blob>        |
  | -----------------------------> |
  |                                |
  |  OpaqueLoginStartResponse      |
  |  response: <OPAQUE blob>       |
  | <----------------------------- |
```

**Request fields:**

| Field | Type | Description |
|-------|------|-------------|
| `username` | `string` | The username logging in. |
| `request` | `bytes` | OPAQUE `CredentialRequest` blob generated by the client. |

**Response fields:**

| Field | Type | Description |
|-------|------|-------------|
| `response` | `bytes` | OPAQUE `CredentialResponse` blob. Contains the server's masked public key and envelope for the client to derive its export key. |

### OpaqueLoginFinish (ID 103)

```
Client                          Server
  |                                |
  |  OpaqueLoginFinishRequest      |
  |  username: "alice"             |
  |  finalization: <OPAQUE blob>   |
  |  identity_key: <32 bytes>      |
  | -----------------------------> |
  |                                |
  |  OpaqueLoginFinishResponse     |
  |  session_token: <32 bytes>     |
  | <----------------------------- |
```

**Request fields:**

| Field | Type | Description |
|-------|------|-------------|
| `username` | `string` | Must match the username from the start request. |
| `finalization` | `bytes` | OPAQUE `CredentialFinalization` blob containing the client's proof of knowledge of the password. The server verifies this against its stored OPAQUE record. |
| `identity_key` | `bytes` | The user's Ed25519 identity public key (32 bytes). The server verifies this matches the key registered during `OpaqueRegisterFinish`. |

**Response fields:**

| Field | Type | Description |
|-------|------|-------------|
| `session_token` | `bytes` | Opaque bearer token (32 bytes). Included in subsequent RPC requests to authenticate the session. The server associates this token with the user's identity and device. |

If login fails (wrong password, unknown username, or identity key mismatch), the server returns an error status in the response frame; the `session_token` field is empty.

---

## Session token usage

After a successful `OpaqueLoginFinish`, the client uses the `session_token` as a bearer credential for all authenticated RPC methods. The token is passed at the QUIC connection level (not per-frame); the server validates it on connection establishment and maintains the association for the lifetime of the connection.

The `Auth` message in `common.proto` carries the token for federation and internal use:

```protobuf
message Auth {
  bytes access_token = 1;
  bytes device_id = 2;
}
```

---

## Further reading

- [Wire Format Overview](overview.md) -- frame format and transport parameters
- [Method ID Reference](envelope-schema.md) -- all 44 method IDs
- [Authentication Service Internals](../internals/authentication-service.md) -- server-side OPAQUE flow and session management
- [RPC Reference](node-service-schema.md) -- all proto definitions
