OAuth clients

OAuth clients provide a framework for delegated and scoped access to the Tailscale API. An OAuth client creates access tokens for API access, instead of using an API key which expires after 90 days (or less if the key has a shorter expiry). OAuth clients support the principle of least privilege by allowing fine-grained control on the access granted to the client using scopes, unlike an API key which grants full access to the Tailscale API.

OAuth clients is currently in alpha.

How it works

You create an OAuth client that defines the scopes to allow when your client application uses the Tailscale API. An example scope is dns:read, which grants read-only access to a tailnet’s DNS settings. Another example is the devices scope, which grants access to read and write access to the list of devices on the tailnet, authorize or remove machines, create auth keys, and manipulate tags on devices.

Scopes are restricted to only the necessary Tailscale API endpoints needed for an operation. For example, tokens with the dns:read scope can access only the following Tailscale API endpoints:

  • /api/v2/tailnet/:tailnet/dns/*
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)

An OAuth client consists of a client ID and a client secret. When you create an OAuth client, Tailscale creates these for you. Within your client application, use the client ID and client secret to request an access token from the Tailscale OAuth token endpoint. Using the access token like an API key, make calls to the Tailscale API. The access token grants permission only for the scopes that were defined when you created the OAuth client.

An access token expires after one hour. For continuous access, shortly before an access token expires, request a new access token from the Tailscale OAuth token endpoint.

OAuth client libraries in popular programming languages can handle the access token generation and renewal.

The Tailscale OAuth implementation is based on the OAuth 2.0 protocol.

Prerequisites

  • You need to be an Owner, Admin, IT Admin, or Network Admin of a tailnet in order to create, revoke, or delete OAuth clients. A user in one of these roles can create an OAuth client with any permissions, including more permissions than the user has.

Setting up an OAuth client

  1. Open the OAuth clients page of the admin console.

  2. In the Generate OAuth client page, select the set of operations that can be performed with tokens created by the new OAuth client. For a given operation, select Read or Write. For a description of the operations, see Scopes.

    The 'Generate OAuth client' page in the admin console
  3. Click Generate client.

  4. In the Generated new OAuth client page, you can see the new OAuth client’s ID and secret. Copy both the client ID and secret, as you need them for your client code. Note that after you close the Generated new OAuth client page, you won’t be able to copy the secret again.

    Store the client secret securely.
    The 'Generate OAuth client' page in the admin console
  5. Click Done.

    Your OAuth client is now configured. Use the client ID and secret when you configure your OAuth client application.

If an OAuth client is created by a user who is later removed or suspended from your tailnet, the OAuth client will continue to function and generate access tokens. Admins can see all configured OAuth clients in the OAuth clients page of the admin console.

Scopes

Scopes define which operations are permitted in access tokens that are created by your client application.

You can use the following scopes in Tailscale OAuth clients:

Scope ID Description Allowed endpoints
all The client has complete access to the tailnet. This scope is not restricted to only access of APIs that existed at the time the client was initially authorized—the all scope also grants access to new APIs created in the future. The all and all:read scopes are the only scopes which can get a list of all API Keys which exist in the tailnet.
  • All endpoints, even endpoints which did not exist when the client was initially authorized.
  • /api/v2/tailnet/:tailnet/keys/:keyid (for any key, not just itself)
all:read The client has read-only access to the tailnet. This scope is not restricted to only read access of APIs that existed at the time the client was initially authorized—the all:read scope also grants read access to new APIs created in the future. The all and all:read scopes are the only scopes which can get a list of all API Keys which exist in the tailnet.
  • All endpoints, even endpoints which did not exist when the client was initially authorized.
  • /api/v2/tailnet/:tailnet/keys/:keyid (for any key, not just itself)
acl The client has access to read and modify the tailnet policy file.
  • /api/v2/tailnet/:tailnet/devices
  • /api/v2/tailnet/:tailnet/acl
  • /api/v2/tailnet/:tailnet/acl/preview
  • /api/v2/tailnet/:tailnet/acl/validate
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)
acl:read The client has access to read and validate the tailnet policy file.
  • /api/v2/tailnet/:tailnet/devices
  • /api/v2/tailnet/:tailnet/acl
  • /api/v2/tailnet/:tailnet/acl/preview
  • /api/v2/tailnet/:tailnet/acl/validate
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)
devices The client has access to read the list of devices on the tailnet, authorize or remove machines, create auth keys, and manipulate tags on devices.
  • /api/v2/tailnet/:tailnet/devices
  • /api/v2/device/:deviceid
  • /api/v2/device/:deviceID/authorized
  • /api/v2/device/:deviceID/key
  • /api/v2/device/:deviceID/tags
  • /api/v2/tailnet/:tailnet/keys (only auth keys, not API keys)
  • /api/v2/tailnet/:tailnet/keys/* (only auth keys, not API keys)
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)
devices:read The client has access to read the list of devices, auth keys, and tags on the tailnet.
  • /api/v2/tailnet/:tailnet/devices
  • /api/v2/device/:deviceid
  • /api/v2/device/:deviceID/authorized
  • /api/v2/device/:deviceID/key
  • /api/v2/device/:deviceID/tags
  • /api/v2/tailnet/:tailnet/keys (only auth keys, not API keys)
  • /api/v2/tailnet/:tailnet/keys/* (only auth keys, not API keys)
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)
dns The client has access to read and manipulate DNS settings.
  • /api/v2/tailnet/:tailnet/dns/*
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)
dns:read The client has access to read DNS settings.
  • /api/v2/tailnet/:tailnet/dns/*
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)
routes The client has access to read or modify subnet router settings, approve and revoke subnet routes, and approve and revoke exit nodes.
  • /api/v2/tailnet/:tailnet/devices
  • /api/v2/device/:deviceID/routes
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)
routes:read The client has access to read subnet router settings and exit node settings.
  • /api/v2/tailnet/:tailnet/devices
  • /api/v2/device/:deviceID/routes
  • /api/v2/tailnet/:tailnet/keys/:keyid (for itself only)

When new Tailscale functionality is provided, we will add it to existing scopes where applicable. That means a scope is not restricted to only access of APIs that existed at the time the client was initially authorized—a scope will contain additional access where it makes sense for new or updated functionality.

You can find documentation for the Tailscale API on GitHub →

Revoking an OAuth client

  1. Open the OAuth clients page of the admin console.

  2. Find the OAuth client that you want to delete and click on Revoke.

  3. Click Revoke OAuth client to confirm you want to revoke the OAuth client.

When you revoke an OAuth client, any active access tokens that were created by the client are also revoked.

Tailscale OAuth token endpoint

The Tailscale OAuth token endpoint is https://api.tailscale.com/api/v2/oauth/token.

Make requests to the Tailscale OAuth token endpoint when you need an access token. The Tailscale OAuth token endpoint accepts requests that conform to the OAuth 2.0 client credentials grant request format, and returns responses that conform to the OAuth 2.0 client credentials grant response format.

OAuth client libraries

Popular programming languages provide OAuth client libraries to simplify your use of OAuth clients. Here are several:

For example, the following Go code shows how to create an OAuth client object that uses your client ID and client secret to generate an access token for calls to the Tailscale API:

package main

import (
        "context"
        "fmt"
        "io/ioutil"
        "log"
        "os"

        "golang.org/x/oauth2/clientcredentials"
)

func main() {
        var oauthConfig = &clientcredentials.Config{
                ClientID:     os.Getenv("OAUTH_CLIENT_ID"),
                ClientSecret: os.Getenv("OAUTH_CLIENT_SECRET"),
                TokenURL:     "https://api.tailscale.com/api/v2/oauth/token",
        }

        client := oauthConfig.Client(context.Background())
        // Replace example.com with your tailnet name.
        resp, err := client.Get("https://api.tailscale.com/api/v2/tailnet/example.com/devices")
        if err != nil {
                log.Fatalf("error getting keys: %v", err)
        }

        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
                log.Fatalf("error reading response body: %v", err)
        }

        fmt.Printf("response: %s", string(body))
}

The example requires that you define environment variables OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET, with their values set to the client ID and client secret that are created when you set up an OAuth client.

Verifying you can generate access tokens

After you set up an OAuth client, an easy way to confirm that you can generate access tokens is to make a curl request to the Tailscale OAuth token endpoint.

 curl -d "client_id=${OAUTH_CLIENT_ID}" -d "client_secret=${OAUTH_CLIENT_SECRET}" \
     "https://api.tailscale.com/api/v2/oauth/token"

The example requires that you define environment variables OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET, with their values set to your client ID and client secret.

Here’s an example response showing the access token:

{"access_token":"tskey-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ","token_type":"Bearer","expires_in":3600,"scope":"devices"}

Generating long-lived auth keys

You cannot generate long-lived auth keys, because they expire after 90 days, or, for one-off keys, once they are used.

Instead of a long-lived auth key, you can generate an OAuth client with the scope devices. Use the OAuth client to generate new auth keys as needed, by making a POST request to the /api/v2/tailnet/:tailnet/keys API method. Note these auth keys require an ACL tag, which can be any tag in your tailnet.

Audit logging of access token creation

In configuration audit logging, an action will be recorded in your audit log whenever an access token is created. The log entry will show the OAuth client ID as the actor, and the time when the access token was created.

If you believe your OAuth client has been compromised, revoke the OAuth client (and set up a new client when you’re ready). Review the configuration audit logs to see whether and how the client and access tokens were used during the period of compromise.

Limitations

  • OAuth clients must be owned by the tailnet, and not by an individual user.
  • An OAuth access token expires after 1 hour—this time cannot be modified.
  • A user can create an OAuth client with greater permissions than their own permissions. We are working on this item.

Last updated

WireGuard is a registered
trademark of Jason A. Donenfeld.

© 2022 Tailscale Inc.

Privacy & Terms