Get started - it's free!
Log in
© 2025

OAuth clients

OAuth clients allow for ongoing access to the Tailscale API using the client credentials flow of the OAuth 2.0 protocol.

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:core scope, which grants access to read and write the list of devices in the tailnet, authorize or remove machines, and manipulate tags on devices.

Tailscale restricts scopes 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:

  • GET /api/v2/tailnet/:tailnet/dns/nameservers
  • GET /api/v2/tailnet/:tailnet/dns/preferences
  • GET /api/v2/tailnet/:tailnet/dns/searchpaths
  • GET /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 API access token from the Tailscale OAuth token endpoint. You use the access token to make calls to the Tailscale API. The access token grants permission only for the scopes that you defined when you created the OAuth client.

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

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

The Tailscale OAuth implementation uses the OAuth 2.0 protocol.

Prerequisites

You need to be an Owner, Admin, Network admin, or IT admin of a tailnet to create, revoke, or delete OAuth clients.

Owners and Admins can create an OAuth client with any scope and any tag that is in the tailnet. Other users can create an OAuth client with only the scopes and tags for which they have permissions. For example, a Network admin cannot grant the devices:core scope, but an IT admin can.

Setting up an OAuth client

  1. Open the Trust credentials page of the admin console.

  2. Select the Credential button.

  3. Select OAuth.

  4. 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, refer to Scopes.

  5. Select Generate credential.

  6. In the Credential created page, you can access 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 Credential created 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
  1. Select Done.

    Your OAuth client is now configured. Use the client ID and secret when you configure your OAuth client application. Note that Tailscale-generated OAuth client secrets are case-sensitive.

If a user creates an OAuth client, the OAuth client will continue to function and generate API access tokens even if the user no longer has access to the tailnet. Admins can access all configured OAuth clients in the Trust credentials page of the admin console.

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 API 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.

Requests to the OAuth token endpoint can include scope and tags request parameters, which specify space-delimited lists of requested scopes and tags, respectively. The OAuth client must have permission to grant the requested scopes and tags. For example, an OAuth client with the all scope (which grants all other scopes as well as all device tags) can request an access token with the devices:core scope and the tag:server tag.

Tags are only relevant for tokens with the devices:core, auth_keys, or all scopes. The OAuth client ignores tags if none of these scopes are present. The tags parameter is not part of the OAuth 2.0 specification, and not all clients might support it.

OAuth client libraries

Popular programming languages provide OAuth client libraries for using 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 API 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 ID.
        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 you create when you set up an OAuth client.

Verifying you can generate API access tokens

After you set up an OAuth client, you can confirm that you can generate API access tokens by making 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 API 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, as soon as you use them.

Instead of a long-lived auth key, you can generate an OAuth client with the auth_keys scope. 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. When you create an OAuth client with the scope auth_keys, you must select one or more tags, which can be any tag or set of tags in your tailnet. You must also specify these tags in the API call.

For example, to assign your device a specific tag, such as tag:server, create an OAuth client with tag:server. When you create the auth key, specify tag:server as the tag for the auth key.

Alternatively, if you need an OAuth client that supports more than one tag, set up tag ownership. For example, to tag some devices with tag:server and others with tag:database:

  1. Set up a tag owner tag:terraform-tag-owner for both tag:server and tag:database:

    {
      "tagOwners": {
        "tag:terraform-tag-owner": ["<your-email-address>"],
        "tag:server": ["tag:terraform-tag-owner"],
        "tag:database": ["tag:terraform-tag-owner"],
      },
    }
    
  2. Create an OAuth client with tag tag:terraform-tag-owner.

  3. Create an auth key from that OAuth client, and specify either tag:server or tag:database as the tag for the auth key.

Shorthand notation for tailnet ID

When you use an access token to make an API call, you can optionally use the value - as the tailnet ID. You can find your tailnet ID in the General page of the admin console. You do not need to specify the tailnet ID.

For example, this command:

curl -u $ACCESS_TOKEN: "https://api.tailscale.com/api/v2/tailnet/example.com/devices"

is equivalent to:

curl -u $ACCESS_TOKEN: "https://api.tailscale.com/api/v2/tailnet/-/devices"

as long as the access token is owned by the example.com tailnet.

You can also include the access token in the request header by using the -H option:

curl -H "Authorization: Bearer $ACCESS_TOKEN" "https://api.tailscale.com/api/v2/tailnet/-/devices"

Register new nodes using OAuth credentials

You can use an OAuth secret directly in tailscale up to register a new node:

tailscale up --auth-key=${OAUTH_CLIENT_SECRET} --advertise-tags=tag:ci

The OAuth client must have the auth_keys scope. Additionally, the tags that you selected when you created the client must own or match the tag passed to --advertise-tags.

The --auth-key flag can accept additional URL-style parameters when used with OAuth secrets:

tailscale up --auth-key='${OAUTH_CLIENT_SECRET}?ephemeral=false&preauthorized=true' --advertise-tags=tag:ci

The available parameters are:

  • ephemeral: register as an ephemeral node (defaults to true)
  • preauthorized: skip manual device approval (defaults to false)
  • baseURL: base URL for the Tailscale API (defaults to https://api.tailscale.com)

get-authkey utility

The get-authkey utility returns a new auth key to stdout, based on environment variables that contain values for your OAuth client ID and secret. Use get-authkey to generate auth keys for scripts or other automation.

All auth keys created from an OAuth client must use tags. You can optionally pass in arguments to get-authkey to specify whether the key type is ephemeral, reusable, and/or pre-authorized.

get-authkey requires Go 1.23 or later.

To build and run get-authkey directly:

  1. Set the following environment variables:

    • TS_API_CLIENT_ID: The OAuth client ID for your tailnet.
    • TS_API_CLIENT_SECRET: The OAuth client secret for your tailnet.
    export TS_API_CLIENT_ID=<clientID> TS_API_CLIENT_SECRET=<secret>
    
  2. Run:

    go run tailscale.com/cmd/get-authkey@latest -tags tag:development
    

You can pass in the following parameters:

  • -tags: Required. Apply the comma-separated list of tags to the auth key.
  • -reusable (Optional): Allocate a reusable auth key. If not set, defaults to false.
  • -ephemeral (Optional): Allocate an ephemeral auth key. If not set, defaults to false.
  • -preauth (Optional): Allocate the auth key as pre-authorized. If not set, defaults to true.

For example:

go run tailscale.com/cmd/get-authkey@latest -reusable -tags tag:development

As an alternative, you can download the get-authkey source code and run it from a local repository:

  1. Clone the tailscale/tailscale repository.

  2. Open a command prompt and change directories to the root of the local tailscale/ folder.

  3. Run get-authkey:

    go run ./cmd/get-authkey/main.go -tags tag:development
    

Scopes

Information about our scopes has moved to the trust credentials topic.

Legacy scopes

Information about our legacy scopes has moved to the trust credentials topic.

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.

Last updated Oct 30, 2025