github.com/safing/portbase@v0.19.5/api/endpoints_meta.go (about) 1 package api 2 3 import ( 4 "encoding/json" 5 "errors" 6 "net/http" 7 ) 8 9 func registerMetaEndpoints() error { 10 if err := RegisterEndpoint(Endpoint{ 11 Path: "endpoints", 12 Read: PermitAnyone, 13 MimeType: MimeTypeJSON, 14 DataFunc: listEndpoints, 15 Name: "Export API Endpoints", 16 Description: "Returns a list of all registered endpoints and their metadata.", 17 }); err != nil { 18 return err 19 } 20 21 if err := RegisterEndpoint(Endpoint{ 22 Path: "auth/permissions", 23 Read: Dynamic, 24 StructFunc: permissions, 25 Name: "View Current Permissions", 26 Description: "Returns the current permissions assigned to the request.", 27 }); err != nil { 28 return err 29 } 30 31 if err := RegisterEndpoint(Endpoint{ 32 Path: "auth/bearer", 33 Read: Dynamic, 34 HandlerFunc: authBearer, 35 Name: "Request HTTP Bearer Auth", 36 Description: "Returns an HTTP Bearer Auth request, if not authenticated.", 37 }); err != nil { 38 return err 39 } 40 41 if err := RegisterEndpoint(Endpoint{ 42 Path: "auth/basic", 43 Read: Dynamic, 44 HandlerFunc: authBasic, 45 Name: "Request HTTP Basic Auth", 46 Description: "Returns an HTTP Basic Auth request, if not authenticated.", 47 }); err != nil { 48 return err 49 } 50 51 if err := RegisterEndpoint(Endpoint{ 52 Path: "auth/reset", 53 Read: PermitAnyone, 54 HandlerFunc: authReset, 55 Name: "Reset Authenticated Session", 56 Description: "Resets authentication status internally and in the browser.", 57 }); err != nil { 58 return err 59 } 60 61 return nil 62 } 63 64 func listEndpoints(ar *Request) (data []byte, err error) { 65 data, err = json.Marshal(ExportEndpoints()) 66 return 67 } 68 69 func permissions(ar *Request) (i interface{}, err error) { 70 if ar.AuthToken == nil { 71 return nil, errors.New("authentication token missing") 72 } 73 74 return struct { 75 Read Permission 76 Write Permission 77 ReadRole string 78 WriteRole string 79 }{ 80 Read: ar.AuthToken.Read, 81 Write: ar.AuthToken.Write, 82 ReadRole: ar.AuthToken.Read.Role(), 83 WriteRole: ar.AuthToken.Write.Role(), 84 }, nil 85 } 86 87 func authBearer(w http.ResponseWriter, r *http.Request) { 88 // Check if authenticated by checking read permission. 89 ar := GetAPIRequest(r) 90 if ar.AuthToken.Read != PermitAnyone { 91 TextResponse(w, r, "Authenticated.") 92 return 93 } 94 95 // Respond with desired authentication header. 96 w.Header().Set( 97 "WWW-Authenticate", 98 `Bearer realm="Portmaster API" domain="/"`, 99 ) 100 http.Error(w, "Authorization required.", http.StatusUnauthorized) 101 } 102 103 func authBasic(w http.ResponseWriter, r *http.Request) { 104 // Check if authenticated by checking read permission. 105 ar := GetAPIRequest(r) 106 if ar.AuthToken.Read != PermitAnyone { 107 TextResponse(w, r, "Authenticated.") 108 return 109 } 110 111 // Respond with desired authentication header. 112 w.Header().Set( 113 "WWW-Authenticate", 114 `Basic realm="Portmaster API" domain="/"`, 115 ) 116 http.Error(w, "Authorization required.", http.StatusUnauthorized) 117 } 118 119 func authReset(w http.ResponseWriter, r *http.Request) { 120 // Get session cookie from request and delete session if exists. 121 c, err := r.Cookie(sessionCookieName) 122 if err == nil { 123 deleteSession(c.Value) 124 } 125 126 // Delete session and cookie. 127 http.SetCookie(w, &http.Cookie{ 128 Name: sessionCookieName, 129 MaxAge: -1, // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0' 130 }) 131 132 // Request client to also reset all data. 133 w.Header().Set("Clear-Site-Data", "*") 134 135 // Set HTTP Auth Realm without requesting authorization. 136 w.Header().Set("WWW-Authenticate", `None realm="Portmaster API"`) 137 138 // Reply with 401 Unauthorized in order to clear HTTP Basic Auth data. 139 http.Error(w, "Session deleted.", http.StatusUnauthorized) 140 }