diff --git a/hscontrol/oidc.go b/hscontrol/oidc.go index e732eb47..f125d290 100644 --- a/hscontrol/oidc.go +++ b/hscontrol/oidc.go @@ -167,7 +167,11 @@ func (a *AuthProviderOIDC) RegisterHandler( extras = append(extras, oauth2.S256ChallengeOption(verifier)) case types.PKCEMethodPlain: // oauth2 does not have a plain challenge option, so we add it manually - extras = append(extras, oauth2.SetAuthURLParam("code_challenge_method", "plain"), oauth2.SetAuthURLParam("code_challenge", verifier)) + extras = append( + extras, + oauth2.SetAuthURLParam("code_challenge_method", "plain"), + oauth2.SetAuthURLParam("code_challenge", verifier), + ) } } @@ -334,8 +338,14 @@ func (a *AuthProviderOIDC) OIDCCallbackHandler( newNode, err := a.handleRegistration(user, *registrationId, nodeExpiry) if err != nil { if errors.Is(err, db.ErrNodeNotFoundRegistrationCache) { - log.Debug().Caller().Str("registration_id", registrationId.String()).Msg("registration session expired before authorization completed") - httpError(writer, NewHTTPError(http.StatusGone, "login session expired, try again", err)) + log.Debug(). + Caller(). + Str("registration_id", registrationId.String()). + Msg("registration session expired before authorization completed") + httpError( + writer, + NewHTTPError(http.StatusGone, "login session expired, try again", err), + ) return } @@ -375,7 +385,11 @@ func extractCodeAndStateParamFromRequest( state := req.URL.Query().Get("state") if code == "" || state == "" { - return "", "", NewHTTPError(http.StatusBadRequest, "missing code or state parameter", errEmptyOIDCCallbackParams) + return "", "", NewHTTPError( + http.StatusBadRequest, + "missing code or state parameter", + errEmptyOIDCCallbackParams, + ) } return code, state, nil @@ -392,7 +406,11 @@ func (a *AuthProviderOIDC) getOauth2Token( if a.cfg.PKCE.Enabled { regInfo, ok := a.registrationCache.Get(state) if !ok { - return nil, NewHTTPError(http.StatusNotFound, "registration not found", errNoOIDCRegistrationInfo) + return nil, NewHTTPError( + http.StatusNotFound, + "registration not found", + errNoOIDCRegistrationInfo, + ) } if regInfo.Verifier != nil { exchangeOpts = []oauth2.AuthCodeOption{oauth2.VerifierOption(*regInfo.Verifier)} @@ -401,7 +419,11 @@ func (a *AuthProviderOIDC) getOauth2Token( oauth2Token, err := a.oauth2Config.Exchange(ctx, code, exchangeOpts...) if err != nil { - return nil, NewHTTPError(http.StatusForbidden, "invalid code", fmt.Errorf("could not exchange code for token: %w", err)) + return nil, NewHTTPError( + http.StatusForbidden, + "invalid code", + fmt.Errorf("could not exchange code for token: %w", err), + ) } return oauth2Token, err @@ -420,7 +442,11 @@ func (a *AuthProviderOIDC) extractIDToken( verifier := a.oidcProvider.Verifier(&oidc.Config{ClientID: a.cfg.ClientID}) idToken, err := verifier.Verify(ctx, rawIDToken) if err != nil { - return nil, NewHTTPError(http.StatusForbidden, "failed to verify id_token", fmt.Errorf("failed to verify ID token: %w", err)) + return nil, NewHTTPError( + http.StatusForbidden, + "failed to verify id_token", + fmt.Errorf("failed to verify ID token: %w", err), + ) } return idToken, nil @@ -435,7 +461,11 @@ func validateOIDCAllowedDomains( if len(allowedDomains) > 0 { if at := strings.LastIndex(claims.Email, "@"); at < 0 || !slices.Contains(allowedDomains, claims.Email[at+1:]) { - return NewHTTPError(http.StatusUnauthorized, "unauthorised domain", errOIDCAllowedDomains) + return NewHTTPError( + http.StatusUnauthorized, + "unauthorised domain", + errOIDCAllowedDomains, + ) } } diff --git a/hscontrol/types/config.go b/hscontrol/types/config.go index 5d9f950f..0adb7610 100644 --- a/hscontrol/types/config.go +++ b/hscontrol/types/config.go @@ -31,10 +31,16 @@ const ( ) var ( - errOidcMutuallyExclusive = errors.New("oidc_client_secret and oidc_client_secret_path are mutually exclusive") - errServerURLSuffix = errors.New("server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable") - errServerURLSame = errors.New("server_url cannot use the same domain as base_domain in a way that could make the DERP and headscale server unreachable") - errInvalidPKCEMethod = errors.New("pkce.method must be either 'plain' or 'S256'") + errOidcMutuallyExclusive = errors.New( + "oidc_client_secret and oidc_client_secret_path are mutually exclusive", + ) + errServerURLSuffix = errors.New( + "server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable", + ) + errServerURLSame = errors.New( + "server_url cannot use the same domain as base_domain in a way that could make the DERP and headscale server unreachable", + ) + errInvalidPKCEMethod = errors.New("pkce.method must be either 'plain' or 'S256'") ) type IPAllocationStrategy string @@ -388,7 +394,8 @@ func validateServerConfig() error { } if viper.IsSet("oidc.use_unverified_email") { - log.Warn().Msg("unverified emails will be accepted during oidc authentication (oidc.use_unverified_email=true)") + log.Warn(). + Msg("unverified emails will be accepted during oidc authentication (oidc.use_unverified_email=true)") } else { log.Warn().Msg("only verified emails will be accepted during oidc authentication (oidc.use_unverified_email=false)") } @@ -396,7 +403,8 @@ func validateServerConfig() error { depr.Log() if viper.IsSet("dns.extra_records") && viper.IsSet("dns.extra_records_path") { - log.Fatal().Msg("Fatal config error: dns.extra_records and dns.extra_records_path are mutually exclusive. Please remove one of them from your config file") + log.Fatal(). + Msg("Fatal config error: dns.extra_records and dns.extra_records_path are mutually exclusive. Please remove one of them from your config file") } // Collect any validation errors and return them all at once