title: Securely exposing a gRPC service with authentication using gRPC-web
body: <p>We are using Improbable's <a href="https://github.com/improbable-eng/grpc-web" rel="noreferrer">gRPC-Web library</a> to expose a gRPC service (implemented in Go) to a Javascript client running in-browser. This service will sit alongside an existing front-end Go service which hosts a REST-based API. The existing service uses session-based authentication to authenticate its users (session cookies + XSRF protection with <a href="https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md#double-submit-cookie" rel="noreferrer">double-submit cookies</a>, which are also verified using some per-session server-side state).</p>
  
  <p>The front-end Go service hosts various API endpoints which are either handled locally or fulfilled by proxying the request to other services. All endpoints are exposed via a Gin middleware handler chain, which implements the aforementioned session authentication and XSRF protection checks. It has been proposed that we host gRPC-Web's <a href="https://github.com/improbable-eng/grpc-web/tree/ebef475aee9558e615643bd7c669ef39cf0999e0/go/grpcwebproxy" rel="noreferrer">gogrpcproxy component</a> behind this existing middleware to expose our gRPC service to the world.</p>
  
  <p>I am interested in ensuring the approach for authenticating the incoming gRPC-Web requests is secure. The following methods have been proposed:</p>
  
  <ul>
  <li><p><strong>Token-based authentication</strong> – i.e. passing bearer tokens in the gRPC request metadata, which are verified by the back-end gRPC service. This matches the authentication model by which native gRPC calls would be authenticated if gRPC-Web was not involved.</p>
  
  <p>In this model, gRPC-Web's responsibility is the implementation of the transport abstraction between browser and server, and marshalling requests to/from the native gRPC representation; authentication is delegated to the backing gRPC service. The gRPC-Web proxy is hosted as a separate endpoint external to the existing REST API.</p></li>
  <li><p><strong>Session-based authentication</strong> – re-use of the existing session authentication middleware. In this model, the grpcweb proxy server is hosted behind the Gin handler chain. Gin performs its usual checks to verify existence of the relevant cookies and XSRF headers prior to admitting the request.</p>
  
  <p>This approach re-uses much of the existing authentication logic. However, it requires the passing of the XSRF header to ensure the request is admitted by the Gin middleware. This is possible in the current implementation by setting request metadata, which is (currently) implemented by setting headers on the outbound HTTP request. However, it is unclear to me whether this:</p>
  
  <ul>
  <li>is appropriate, as it appears to be a layer violation by exploiting the implementation detail that metadata is currently passed as HTTP headers. This is not documented and could conceivably change;</li>
  <li>is compatible with gRPC-Web's websocket transport, which does not appear to propagate metadata into headers, as the websocket transport is dialled prior to any requests being transmitted;</li>
  <li>suffers potential security issues in future, as the long-lived gRPC-Web transport connection to the front-end service is only authenticated by the front-end proxy when first established, rather than continually on every request (unless the gRPC service also validates the request metadata).</li>
  </ul></li>
  </ul>
  
  <p>My understanding is that gRPC-Web seeks to emulate the gRPC transport between a browser and server, so accordingly implements no specific authentication logic. The standard gRPC mechanisms for passing authentication details make no allowance for implicit session-based state, so my preference is the token-based approach.</p>
  
  <p>Is this a reasonable analysis of the available options?</p>