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
This commit is contained in:
Florian Preinstorfer
2026-02-28 20:36:21 +01:00
committed by nblock
parent acddd73183
commit 9baa795ddb
9 changed files with 22 additions and 21 deletions

View File

@@ -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)

View File

@@ -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")

View File

@@ -54,8 +54,8 @@ Headscale server at `/swagger` for details.
```console
curl -H "Authorization: Bearer <API_KEY>" \
-d user=<USER> -d key=<REGISTRATION_KEY> \
https://headscale.example.com/api/v1/node/register
--json '{"user": "<USER>", "authId": "AUTH_ID>"}' \
https://headscale.example.com/api/v1/auth/register
```
## gRPC

View File

@@ -48,10 +48,10 @@ headscale users create <USER>
```
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 <USER> --key <REGISTRATION_KEY>
headscale auth register --user <USER> --auth-id <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 <USER>
```
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 <USER> --key <REGISTRATION_KEY>
headscale auth register --user <USER> --auth-id <AUTH_ID>
```
Headscale checks that `<USER>` is allowed to register a node with the specified tag(s) and then transfers ownership

View File

@@ -45,10 +45,10 @@ tailscale up --login-server <YOUR_HEADSCALE_URL> --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 <USER> --key <REGISTRATION_KEY>
headscale auth register --user <USER> --auth-id <AUTH_ID>
```
All previously assigned tags get removed and the node is now owned by the user specified in the above command.

View File

@@ -110,19 +110,19 @@ tailscale up --login-server <YOUR_HEADSCALE_URL>
```
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 <USER> --key <REGISTRATION_KEY>
headscale auth register --user <USER> --auth-id <AUTH_ID>
```
=== "Container"
```shell
docker exec -it headscale \
headscale nodes register --user <USER> --key <REGISTRATION_KEY>
headscale auth register --user <USER> --auth-id <AUTH_ID>
```
### [Pre authenticated key](../ref/registration.md#pre-authenticated-key)

View File

@@ -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),

View File

@@ -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")

View File

@@ -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