using System; using System.Net; namespace Laservall.Solidworks.Server { /// /// Per-session auth token. Passed to browser via URL fragment (#token=xxx), /// returned via Authorization: Bearer header or ?token= query param. /// internal sealed class AuthTokenMiddleware { private readonly string _token; public AuthTokenMiddleware() { _token = Guid.NewGuid().ToString("N"); } public string Token => _token; public bool IsAuthorized(HttpListenerRequest request) { if (request.Url.AbsolutePath == "/") { return true; } string authHeader = request.Headers["Authorization"]; if (!string.IsNullOrEmpty(authHeader)) { const string bearerPrefix = "Bearer "; if (authHeader.StartsWith(bearerPrefix, StringComparison.OrdinalIgnoreCase)) { string headerToken = authHeader.Substring(bearerPrefix.Length).Trim(); if (string.Equals(headerToken, _token, StringComparison.Ordinal)) { return true; } } } // ?token= fallback for SSE/download (can't set custom headers) string queryToken = request.QueryString["token"]; if (!string.IsNullOrEmpty(queryToken)) { return string.Equals(queryToken, _token, StringComparison.Ordinal); } return false; } public static void RejectUnauthorized(HttpListenerResponse response) { response.StatusCode = 401; response.ContentType = "application/json; charset=utf-8"; byte[] body = System.Text.Encoding.UTF8.GetBytes("{\"error\":\"Unauthorized\"}"); response.ContentLength64 = body.Length; response.OutputStream.Write(body, 0, body.Length); response.Close(); } } }