diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 7a4fb5b6c..462b18b6e 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -1118,33 +1118,31 @@ func init() { tailscale.I_Acknowledge_This_API_Is_Unstable = true } -// resolveAuthKey either returns v unchanged (in the common case) -// or, if it starts with "oauth:" parses it as one of: +// resolveAuthKey either returns v unchanged (in the common case) or, if it +// starts with "tskey-client-" (as Tailscale OAuth secrets do) parses it like // -// oauth2:CLIENT_ID:CLIENT_SECRET?ephemeral=false&tags=foo,bar&preauthorized=BOOL -// oauth2:CLIENT_ID:CLIENT_SECRET:BASE_URL?... +// tskey-client-xxxx[?ephemeral=false&tags=foo,bar&preauthorized=BOOL&baseURL=...] // -// and does the OAuth2 dance to get and return an authkey. The "ephemeral" property -// defaults to true if unspecified. The "preauthorized" defaults to false. -// -// If the BASE_URL argument is not provided, it defaults to https://api.tailscale.com. +// and does the OAuth2 dance to get and return an authkey. The "ephemeral" +// property defaults to true if unspecified. The "preauthorized" defaults to +// false. The "baseURL" defaults to +// https://api.tailscale.com. func resolveAuthKey(ctx context.Context, v string) (string, error) { - suff, ok := strings.CutPrefix(v, "oauth:") - if !ok { + if !strings.HasPrefix(v, "tskey-client-") { return v, nil } if !envknob.Bool("TS_EXPERIMENT_OAUTH_AUTHKEY") { return "", errors.New("oauth authkeys are in experimental status") } - pos, named, _ := strings.Cut(suff, "?") + clientSecret, named, _ := strings.Cut(v, "?") attrs, err := url.ParseQuery(named) if err != nil { return "", err } for k := range attrs { switch k { - case "ephemeral", "preauthorized", "tags": + case "ephemeral", "preauthorized", "tags", "baseURL": default: return "", fmt.Errorf("unknown attribute %q", k) } @@ -1173,18 +1171,13 @@ func resolveAuthKey(ctx context.Context, v string) (string, error) { tags = strings.Split(v, ",") } - f := strings.SplitN(pos, ":", 3) - if len(f) < 2 || len(f) > 3 { - return "", errors.New("invalid auth key format; want oauth2:CLIENT_ID:CLIENT_SECRET[:BASE_URL]") - } - clientID, clientSecret := f[0], f[1] baseURL := "https://api.tailscale.com" - if len(f) == 3 { - baseURL = f[2] + if v := attrs.Get("baseURL"); v != "" { + baseURL = v } credentials := clientcredentials.Config{ - ClientID: clientID, + ClientID: "some-client-id", // ignored ClientSecret: clientSecret, TokenURL: baseURL + "/api/v2/oauth/token", Scopes: []string{"device"},