Custom App with Reverse Proxy

Providing authentication for custom applications with the reverse proxy.


The proxy is a small application that will sit in front of your application. It will receive requests for your app, make sure the users are properly identified, and pass the request on to your application.


In a typical scenario you will run the proxy on the same host that runs your application. The proxy listens for incoming requests, makes sure they are from valid users, and then passes those requests on to your application.

The reverse proxy sits in front of your custom web application and filters incoming requests. By default it makes sure that all incoming requests have been authenticated using before your application even sees the request.

Using this model, you don’t have to worry about the nitty-gritty of correctly implementing authentication protocols, and your application is protected from unauthenticated requests.

Your application can then inspect the request headers to determine which user has been authenticated and collect other biographical information.

Getting Started

In the console, create a new proxy application.

If you haven’t already, install the client software with

curl -sL | bash


Copy the token parameter and pass it the the proxy:

$ grooveid proxy --token=$YOUR_TOKEN

By default the proxy will listen on tcp/443 and tcp/80 and will proxy requests to localhost:8000. It will automatically obtain a TLS certificate from Lets Encrypt if possible.

Handling Requests

The proxy will ensure that each request comes from a valid, authenticated user. Your upstream application receives information about the remote user via HTTP headers that are added to the request. An example request might look like:

Authorization: Basic cGdAaW5pdGVjaC5iaXo6
X-Grooveid-Full-Name: Peter Gibbons
X-Grooveid-Session-Expires: Fri, 27 Jul 2018 16:27:22 GMT
X-Grooveid-User-Name: pg
X-Grooveid-User: OtczVCbP71qDGQ
X-Grooveid-Auth-Type: session

The headers added to the request are:

  • X-Grooveid-User-Name - the unix user name of the remote user.
  • X-Grooveid-Email - the user’s email address. (also included as X-Remote-User)
  • X-Grooveid-Full-Name - the user’s full name
  • X-Grooveid-User - a globally unique identifier for the user which will remain unchanged even if the email address or user name changes.
  • X-Grooveid-Session-Expires - The time when the user’s session expires
  • X-Grooveid-Auth-Type - The kind of proof that was provided. bearer means that an API key was used. session means that a short-lived signed cookie corresponding to a new or existing session was presented.
  • X-Forwarded-For - the remote address of the request
  • X-Grooveid-Access-Check - The URL for checking access during the request.
  • Authorization - a synthetic basic authorization header where the username is the user’s email address and the password is blank.

Access Check

The upstream server receives a URL in the X-Grooveid-Access-Check request header. During the request, you may query this URL to determine if the remote user is a member of a particular group. An example request:

POST /__grooveid/check_access?pt=HvLhvlczrbZD9v HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 114


The proxy server will respond with 200 Ok if the remote user is a member of each of the groups specified. Otherwise, the proxy server will respond with 403 Forbidden.

The forbidden response will include a Location response header. If you direct the user to that URL they will be prompted to join or activate the group. When the process completes, the user will be sent to the url given in the next parameter to the initial access check request.

The access check endpoint accepts the following parameters:

  • group - which group to check (may be specified multiple times)
  • next - A URL to direct the user back to when the access request flow completes.
  • op - If “or” is specified then access to any of the groups is sufficient to allow access. If “and” is specified, then the user must be a member of all groups. The default is “and.”

Note: The access check URL is valid only while the request is being processed. After the request is complete, the access check URL is invalid.

This endpoint also returns a JSON body that includes the status information about each group:

    "GroupID": "Z9Or13VAbDKGMP",
    "StatusCode": 401,
    "Location": ""
    "GroupID": "uGHRZBr98fWqCw",
    "StatusCode": 200

Note: When op=or and the user is already an active member of one of the groups you provided, then because of the short-circuit evaluation, other groups will not be checked, and thus will not appear in the returned list. There is no short-circuit evaluation when op=and is given.


You can configure the proxy with a configuration file, with environment variables, or command line flags.

Example configuration file:

listen = :443
tls = on
cert = /var/secrets/tls.cert
key = /var/secrets/tls.key
upstream = "http://localhost:8000"

token = "6b3xeo0mthu8wy.o9wpCxLMUtSKNF.OEI2YjESGkR01noWtjgH9CBv3bQH"

listen = :80

[path "/public"]
        auth = none

[path "/private"]
        auth = required

[path "/api"]
        auth = optional

[path "/admin"]
        auth = required
        upstream = http://localhost:9999

Specify the configuration with the -C flag, for example:

grooveid proxy -C /etc/grooveid-proxy.conf

The same configuration using the command line (and defaults):

grooveid proxy \
    --listen :443 \
    --cert /var/secrets/tls.cert \
    --key /var/secrets/tls.key \
    --upstream http://localhost:8000 \
    --token 6b3xeo0mthu8wy.o9wpCxLMUtSKNF.OEI2YjESGkR01noWtjgH9CBv3bQH \
    --redirect-listen :80 \
    -c 'path_/public_auth=none' \
    -c 'path_/private_auth=required' \
    -c 'path_/api_auth=optional' \
    -c 'path_/admin_auth=required' \
    -c 'path_/admin_upstream=http://localhost:9999'

The same configuration using environment variables:

export GV_PROXY_LISTEN=:443
export GV_PROXY_CERT=/var/secrets/tls.cert
export GV_PROXY_KEY=/var/secrets/tls.key
export GV_PROXY_UPSTREAM=http://localhost:8000
export GV_AUTH_TOKEN=6b3xeo0mthu8wy.o9wpCxLMUtSKNF.OEI2YjESGkR01noWtjgH9CBv3bQH
export GV_PATH_/public_AUTH=none
export GV_PATH_/private_AUTH=required
export GV_PATH_/api_AUTH=optional
export GV_PATH_/admin_AUTH=required
export GV_PATH_/admin_UPSTREAM=http://localhost:9999


The following settings can be used to configure the proxy.


Environment Variable: GV_PROXY_LISTEN

Commandline Flag: --listen

Default: :443

Specifies the address and port where the proxy interface should listen.


Section: proxy

Name: tls

Environment Variable: GV_PROXY_TLS

Commandline Flag: --tls

Default: true

If true then the proxy should listen for encrypted requests, otherwise the requests are expected to be plaintext.


Section: proxy

Name: cert

Environment Variable: GV_PROXY_CERT

Commandline Flag: --cert

Default: empty

If this and proxy.key are specified then serve requests over TLS using the key and certificate. If not specified, then use the ACME protocol to obtain a certificate on demand.


Section: proxy

Name: key

Environment Variable: GV_PROXY_KEY

Commandline Flag: --key

Default: empty

If this and proxy.cert are specified then serve requests over TLS using the key and certificate. If not specified, then use the ACME protocol to obtain a certificate on demand.

Section: proxy

Name: name

Environment Variable: GV_PROXY_NAME

Commandline Flag: --name

Default: empty

Specifies the host name of the server. If not specified, then the server name is determined the first time a request is received.


Section: proxy

Name: auth

Environment Variable: GV_PROXY_AUTH

Commandline Flag: --auth

Default: required

Specifies the default authentication mode for the server, which must be one of:

  • none - no authentication is performed.
  • optional - when authentication information is present, verify it and pass it to the upstream server, but do not require it.
  • required - the remote user must be authenticated in order to pass a request to the upstream server.

Note: This setting may be overridden for a particular path prefix in a prefix section.


Section: proxy

Name: upstream

Environment Variable: GV_PROXY_UPSTREAM

Commandline Flag: --upstream

Default: http://localhost:8000

Specifies the default upstream server for the proxy.

Note: This setting may be overridden for a particular path prefix in a prefix section.


Section: proxy

Name: privateaddress


Commandline Flag: --privateaddress

Default: (empty)

Specifies the address that the upstream service uses to make metadata requests, such as access checks, while processing the request. If not specified, the URL will be constructed from the inbound request. Change this setting if the URL in the X-Grooveid-Access header is incorrect.


Section: proxy

Name: cookiekey

Environment Variable: GV_PROXY_COOKIEKEY

Commandline Flag: --cookiekey

Default: (empty)

Specifies the key used to sign session cookies. If not specified, a key will be generated at startup. This must be a PEM-encoded ECDSA private key on the P-256 curve.


Section: proxy

Name: cookiedomain

Environment Variable: GV_PROXY_COOKIEDOMAIN

Default: (empty)

Specifies the domain to be used when issuing session cookies.


Section: auth

Name: token

Environment Variable: GV_AUTH_TOKEN

Commandline Flag: --token

Default: (empty)

Specifies the token that associates this proxy with an application in Get this value from the console.


Section: auth

Name: server

Environment Variable: GV_AUTH_SERVER

Commandline Flag: --auth-server


Specifies the address of the API server. Under normal circumstances, this should not need to change.


You can override the default settings for a particular URL prefix by specifying a prefix section. When processing a request, the longest prefix that matches is used.


auth = required

[prefix /public]
auth = none

[prefix /api]
auth = optional


Section: prefix

Subsection: a URL path prefix

Name: auth

Overrides the authentication mode specified by proxy.auth for this prefix.


Section: prefix

Subsection: a URL path prefix

Name: upstream

Overrides the upstream server specified by proxy.upstream for this prefix.


Section: redirect

Name: listen

Environment Variable: GV_REDIRECT_LISTEN

Commandline Flag: --redirect-listen

Default: :80

The redirector is used to redirect plaintext http requests to encrypted https requests. This option specified the address and port where the plaintext redirector should listen.


Section: acme

Name: server

Environment Variable: GV_ACME_SERVER

Commandline Flag: --acme-server


Specifies the ACME protocol server to use to issue certificates on demand. For testing use the Let’s Encrypt staging server

Section: acme

Name: email

Environment Variable: GV_ACME_EMAIL

Commandline Flag: --acme-email

Default: (empty)

Specifies the email address to use when registering a certificate using the ACME protocol. By default it derives the email address from the server name given in

API Access

You can use API keys to access your application. To create an API key, select the API Keys tab, then Add.

Create an API key

Click the pencil icon next to Scopes and assign your new API key at least the user scope. Click Save.

Assign Scopes to the API key

You can specify the API key in the Authorization header, as the username or password in HTTP basic authentication.

Using the authorization header:

curl -H "Authorization: Bearer API_KEY
GET / HTTP/1.1
Authorization: Bearer API_KEY

Using the username field in basic authentication:

curl -u "API_KEY:"
Last modified May 12, 2020: refactor docs (d7a7a5c1d)