From 9baa795ddbb4eda613142b9de2f1cd15e2596a96 Mon Sep 17 00:00:00 2001 From: Florian Preinstorfer Date: Sat, 28 Feb 2026 20:36:21 +0100 Subject: [PATCH] Update docs for auth-id changes - Replace "headscale nodes register" with "headscale auth register" - Update from registration key to Auth ID - Fix API example to register a node --- CHANGELOG.md | 1 + cmd/headscale/cli/debug.go | 2 +- docs/ref/api.md | 4 ++-- docs/ref/registration.md | 8 ++++---- docs/ref/tags.md | 4 ++-- docs/usage/getting-started.md | 6 +++--- hscontrol/auth.go | 4 ++-- hscontrol/handlers.go | 12 ++++++------ hscontrol/oidc.go | 2 +- 9 files changed, 22 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c04ac477..c72424f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ A new `headscale auth` CLI command group supports the approval flow: - Remove deprecated `namespace`/`ns` command aliases for `users` and `machine`/`machines` aliases for `nodes` [#3093](https://github.com/juanfont/headscale/pull/3093) - Add SSH `check` action support with OIDC and CLI-based approval flows [#1850](https://github.com/juanfont/headscale/pull/1850) - Add `headscale auth register`, `headscale auth approve`, and `headscale auth reject` CLI commands [#1850](https://github.com/juanfont/headscale/pull/1850) +- Add `auth` related routes to the API. The `auth/register` endpoint now expects data as JSON [#1850](https://github.com/juanfont/headscale/pull/1850) - Deprecate `headscale nodes register --key` in favour of `headscale auth register --auth-id` [#1850](https://github.com/juanfont/headscale/pull/1850) - Generalise auth templates into reusable `AuthSuccess` and `AuthWeb` components [#1850](https://github.com/juanfont/headscale/pull/1850) - Unify auth pipeline with `AuthVerdict` type, supporting registration, reauthentication, and SSH checks [#1850](https://github.com/juanfont/headscale/pull/1850) diff --git a/cmd/headscale/cli/debug.go b/cmd/headscale/cli/debug.go index 9e4a67fd..1f934f0b 100644 --- a/cmd/headscale/cli/debug.go +++ b/cmd/headscale/cli/debug.go @@ -31,7 +31,7 @@ var debugCmd = &cobra.Command{ var createNodeCmd = &cobra.Command{ Use: "create-node", - Short: "Create a node that can be registered with `nodes register <>` command", + Short: "Create a node that can be registered with `auth register <>` command", RunE: grpcRunE(func(ctx context.Context, client v1.HeadscaleServiceClient, cmd *cobra.Command, args []string) error { user, _ := cmd.Flags().GetString("user") name, _ := cmd.Flags().GetString("name") diff --git a/docs/ref/api.md b/docs/ref/api.md index e8c65e24..4337da13 100644 --- a/docs/ref/api.md +++ b/docs/ref/api.md @@ -54,8 +54,8 @@ Headscale server at `/swagger` for details. ```console curl -H "Authorization: Bearer " \ - -d user= -d key= \ - https://headscale.example.com/api/v1/node/register + --json '{"user": "", "authId": "AUTH_ID>"}' \ + https://headscale.example.com/api/v1/auth/register ``` ## gRPC diff --git a/docs/ref/registration.md b/docs/ref/registration.md index 982290c5..17cf4894 100644 --- a/docs/ref/registration.md +++ b/docs/ref/registration.md @@ -48,10 +48,10 @@ headscale users create ``` Usually, a browser window with further instructions is opened. This page explains how to complete the registration - on your Headscale server and it also prints the registration key required to approve the node: + on your Headscale server and it also prints the Auth ID required to approve the node: ```console - headscale nodes register --user --key + headscale auth register --user --auth-id ``` Congrations, the registration of your personal node is complete and it should be listed as "online" in the output of @@ -79,10 +79,10 @@ headscale users create ``` Usually, a browser window with further instructions is opened. This page explains how to complete the registration - on your Headscale server and it also prints the registration key required to approve the node: + on your Headscale server and it also prints the Auth ID required to approve the node: ```console - headscale nodes register --user --key + headscale auth register --user --auth-id ``` Headscale checks that `` is allowed to register a node with the specified tag(s) and then transfers ownership diff --git a/docs/ref/tags.md b/docs/ref/tags.md index 7e08be13..2be69718 100644 --- a/docs/ref/tags.md +++ b/docs/ref/tags.md @@ -45,10 +45,10 @@ tailscale up --login-server --advertise-tags= --force-reaut ``` Usually, a browser window with further instructions is opened. This page explains how to complete the registration on -your Headscale server and it also prints the registration key required to approve the node: +your Headscale server and it also prints the Auth ID required to approve the node: ```console -headscale nodes register --user --key +headscale auth register --user --auth-id ``` All previously assigned tags get removed and the node is now owned by the user specified in the above command. diff --git a/docs/usage/getting-started.md b/docs/usage/getting-started.md index 90ced39f..5eb11226 100644 --- a/docs/usage/getting-started.md +++ b/docs/usage/getting-started.md @@ -110,19 +110,19 @@ tailscale up --login-server ``` Usually, a browser window with further instructions is opened. This page explains how to complete the registration on -your headscale server and it also prints the registration key required to approve the node: +your headscale server and it also prints the Auth ID required to approve the node: === "Native" ```shell - headscale nodes register --user --key + headscale auth register --user --auth-id ``` === "Container" ```shell docker exec -it headscale \ - headscale nodes register --user --key + headscale auth register --user --auth-id ``` ### [Pre authenticated key](../ref/registration.md#pre-authenticated-key) diff --git a/hscontrol/auth.go b/hscontrol/auth.go index 3a066d91..f24cfc0b 100644 --- a/hscontrol/auth.go +++ b/hscontrol/auth.go @@ -327,7 +327,7 @@ func (h *Headscale) reqToNewRegisterResponse( authRegReq := types.NewRegisterAuthRequest(nodeToRegister) - log.Info().Msgf("new followup node registration using key: %s", newAuthID) + log.Info().Msgf("new followup node registration using auth id: %s", newAuthID) h.state.SetAuthCacheEntry(newAuthID, authRegReq) return &tailcfg.RegisterResponse{ @@ -452,7 +452,7 @@ func (h *Headscale) handleRegisterInteractive( authRegReq, ) - log.Info().Msgf("starting node registration using key: %s", authID) + log.Info().Msgf("starting node registration using auth id: %s", authID) return &tailcfg.RegisterResponse{ AuthURL: h.authProvider.RegisterURL(authID), diff --git a/hscontrol/handlers.go b/hscontrol/handlers.go index 57469ce0..f0f1501c 100644 --- a/hscontrol/handlers.go +++ b/hscontrol/handlers.go @@ -284,18 +284,18 @@ func (a *AuthProviderWeb) AuthHandler( func authIDFromRequest(req *http.Request) (types.AuthID, error) { raw, err := urlParam[string](req, "auth_id") if err != nil { - return "", NewHTTPError(http.StatusBadRequest, "invalid registration id", fmt.Errorf("parsing auth_id from URL: %w", err)) + return "", NewHTTPError(http.StatusBadRequest, "invalid auth id", fmt.Errorf("parsing auth_id from URL: %w", err)) } // We need to make sure we dont open for XSS style injections, if the parameter that // is passed as a key is not parsable/validated as a NodePublic key, then fail to render // the template and log an error. - registrationId, err := types.AuthIDFromString(raw) + authId, err := types.AuthIDFromString(raw) if err != nil { - return "", NewHTTPError(http.StatusBadRequest, "invalid registration id", fmt.Errorf("parsing auth_id from URL: %w", err)) + return "", NewHTTPError(http.StatusBadRequest, "invalid auth id", fmt.Errorf("parsing auth_id from URL: %w", err)) } - return registrationId, nil + return authId, nil } // RegisterHandler shows a simple message in the browser to point to the CLI @@ -307,7 +307,7 @@ func (a *AuthProviderWeb) RegisterHandler( writer http.ResponseWriter, req *http.Request, ) { - registrationId, err := authIDFromRequest(req) + authId, err := authIDFromRequest(req) if err != nil { httpError(writer, err) return @@ -319,7 +319,7 @@ func (a *AuthProviderWeb) RegisterHandler( _, err = writer.Write([]byte(templates.AuthWeb( "Node registration", "Run the command below in the headscale server to add this node to your network:", - fmt.Sprintf("headscale auth register --auth-id %s --user USERNAME", registrationId.String()), + fmt.Sprintf("headscale auth register --auth-id %s --user USERNAME", authId.String()), ).Render())) if err != nil { log.Error().Err(err).Msg("failed to write register response") diff --git a/hscontrol/oidc.go b/hscontrol/oidc.go index ee6dbeb9..72c4c1d0 100644 --- a/hscontrol/oidc.go +++ b/hscontrol/oidc.go @@ -336,7 +336,7 @@ func (a *AuthProviderOIDC) OIDCCallbackHandler( newNode, err := a.handleRegistration(user, authInfo.AuthID, nodeExpiry) if err != nil { if errors.Is(err, db.ErrNodeNotFoundRegistrationCache) { - log.Debug().Caller().Str("registration_id", authInfo.AuthID.String()).Msg("registration session expired before authorization completed") + log.Debug().Caller().Str("auth_id", authInfo.AuthID.String()).Msg("registration session expired before authorization completed") httpError(writer, NewHTTPError(http.StatusGone, "login session expired, try again", err)) return