feat: implement OAuth 2.0 Device Authorization Grant (RFC 8628) for WebDAV/CalDAV/CardDAV
Adds full Device Authorization Grant flow so DAV clients (rclone, etc.) can authenticate without browser-based OAuth redirects. New files: - Domain entity: DeviceCode with status lifecycle (pending/authorized/denied/expired) - Port: DeviceCodeStoragePort trait (7 async methods) - DTOs: request/response types for all device auth endpoints - Repository: DeviceCodePgRepository (PostgreSQL implementation) - Service: DeviceAuthService (initiate, verify, approve, deny, poll, cleanup) - Handler: 6 HTTP endpoints (2 public + 4 protected) - Static: device-verify.html verification page served at /device Flow: 1. Client POST /api/auth/device/authorize → device_code + user_code 2. User opens /device?code=XXXX in browser, approves 3. Client polls POST /api/auth/device/token → receives JWT tokens 4. Client uses Bearer token with existing WebDAV/CalDAV/CardDAV middleware Schema: auth.device_codes table + device_code_status enum added to schema.sql Closes #152
This commit is contained in:
@@ -24,6 +24,7 @@ pub fn create_web_routes() -> Router<Arc<AppState>> {
|
||||
.route("/login", get(serve_login_page))
|
||||
.route("/profile", get(serve_profile_page))
|
||||
.route("/admin", get(serve_admin_page))
|
||||
.route("/device", get(serve_device_verify_page))
|
||||
// Serve static files with compression + cache headers
|
||||
.fallback_service(static_service)
|
||||
.layer(CompressionLayer::new().br(true).gzip(true))
|
||||
@@ -47,3 +48,8 @@ async fn serve_profile_page() -> Html<&'static str> {
|
||||
async fn serve_admin_page() -> Html<&'static str> {
|
||||
Html(include_str!("../../../static/admin.html"))
|
||||
}
|
||||
|
||||
/// Serve the device verification page (RFC 8628 Device Authorization Grant)
|
||||
async fn serve_device_verify_page() -> Html<&'static str> {
|
||||
Html(include_str!("../../../static/device-verify.html"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user