Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.26

require (
filippo.io/csrf v0.2.1
gopkg.in/square/go-jose.v2 v2.6.0
github.com/go-jose/go-jose/v4 v4.1.4
tailscale.com v1.94.2
)

Expand Down
12 changes: 2 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ github.com/creachadair/taskgroup v0.13.2 h1:3KyqakBuFsm3KkXi/9XIb0QcA8tEzLHLgaoi
github.com/creachadair/taskgroup v0.13.2/go.mod h1:i3V1Zx7H8RjwljUEeUWYT30Lmb9poewSb2XI1yTwD0g=
github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0=
github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk=
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa/go.mod h1:Nx87SkVqTKd8UtT+xu7sM/l+LgXs6c0aHrlKusR+2EQ=
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc h1:8WFBn63wegobsYAX0YjD+8suexZDga5CctH4CCTx2+8=
Expand All @@ -74,6 +72,8 @@ github.com/gaissmai/bart v0.18.0 h1:jQLBT/RduJu0pv/tLwXE+xKPgtWJejbxuXAR+wLJafo=
github.com/gaissmai/bart v0.18.0/go.mod h1:JJzMAhNF5Rjo4SF4jWBrANuJfqY+FvsFhW7t1UZJ+XY=
github.com/github/fakeca v0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I=
github.com/github/fakeca v0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo=
github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA=
github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-json-experiment/json v0.0.0-20250813024750-ebf49471dced h1:Q311OHjMh/u5E2TITc++WlTP5We0xNseRMkHDyvhW7I=
github.com/go-json-experiment/json v0.0.0-20250813024750-ebf49471dced/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
Expand Down Expand Up @@ -140,8 +140,6 @@ github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaAS
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus-community/pro-bing v0.4.0 h1:YMbv+i08gQz97OZZBwLyvmmQEEzyfyrrjEaAchdy3R4=
github.com/prometheus-community/pro-bing v0.4.0/go.mod h1:b7wRYZtCcPmt4Sz319BykUU241rWLe1VFXyiyWK/dH4=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
Expand All @@ -152,8 +150,6 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e h1:PtWT87weP5LWHEY//SWsYkSO3RWRZo4OSWagh3YD2vQ=
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e/go.mod h1:XrBNfAFN+pwoWuksbFS9Ccxnopa15zJGgXRFN90l3K4=
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 h1:Gzfnfk2TWrk8Jj4P4c1a3CtQyMaTVCznlkLZI++hok4=
Expand Down Expand Up @@ -223,10 +219,6 @@ golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20250205023644-9414b50a5633 h1:2gap+Kh/3F47cO6hAu3idFvsJ0ue6TRcEi2IUkv/F8k=
gvisor.dev/gvisor v0.0.0-20250205023644-9414b50a5633/go.mod h1:5DMfjtclAbTIjbXqO1qCe2K5GKKxWz2JHvCChuTcJEM=
honnef.co/go/tools v0.7.0-0.dev.0.20251022135355-8273271481d0 h1:5SXjd4ET5dYijLaf0O3aOenC0Z4ZafIWSpjUzsQaNho=
Expand Down
2 changes: 1 addition & 1 deletion server/extraclaims_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"reflect"
"testing"

"gopkg.in/square/go-jose.v2/jwt"
"github.com/go-jose/go-jose/v4/jwt"
"tailscale.com/types/key"
"tailscale.com/types/views"
)
Expand Down
2 changes: 1 addition & 1 deletion server/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"sort"
"testing"

"gopkg.in/square/go-jose.v2"
"github.com/go-jose/go-jose/v4"
"tailscale.com/client/local"
"tailscale.com/client/tailscale/apitype"
"tailscale.com/tailcfg"
Expand Down
2 changes: 1 addition & 1 deletion server/oauth-metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"fmt"
"net/http"

"gopkg.in/square/go-jose.v2"
"github.com/go-jose/go-jose/v4"
"tailscale.com/types/views"
)

Expand Down
2 changes: 1 addition & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (
"time"

"filippo.io/csrf"
"gopkg.in/square/go-jose.v2"
"github.com/go-jose/go-jose/v4"
"tailscale.com/client/local"
"tailscale.com/client/tailscale/apitype"
"tailscale.com/ipn"
Expand Down
4 changes: 2 additions & 2 deletions server/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"strings"
"time"

"gopkg.in/square/go-jose.v2/jwt"
"github.com/go-jose/go-jose/v4/jwt"
"tailscale.com/client/tailscale/apitype"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
Expand Down Expand Up @@ -597,7 +597,7 @@ func (s *IDPServer) issueTokens(w http.ResponseWriter, r *http.Request, ar *Auth
}

// Create an OIDC token using this issuer's signer.
token, err := jwt.Signed(signer).Claims(tsClaimsWithExtra).CompactSerialize()
token, err := jwt.Signed(signer).Claims(tsClaimsWithExtra).Serialize()
if err != nil {
writeHTTPError(w, r, http.StatusInternalServerError, ecServerError, "error creating JWT token", err)
return
Expand Down
29 changes: 18 additions & 11 deletions server/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import (
"testing"
"time"

"gopkg.in/square/go-jose.v2/jwt"
jose "github.com/go-jose/go-jose/v4"
"github.com/go-jose/go-jose/v4/jwt"
"tailscale.com/client/tailscale/apitype"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
Expand Down Expand Up @@ -50,7 +51,7 @@ func TestResourceIndicators(t *testing.T) {
t.Fatalf("failed to unmarshal response: %v", err)
}
// Decode JWT to check audience
token, err := jwt.ParseSigned(resp.IDToken)
token, err := jwt.ParseSigned(resp.IDToken, []jose.SignatureAlgorithm{jose.RS256})
if err != nil {
t.Fatalf("failed to parse JWT: %v", err)
}
Expand Down Expand Up @@ -87,7 +88,7 @@ func TestResourceIndicators(t *testing.T) {
t.Fatalf("failed to unmarshal response: %v", err)
}
// Decode JWT to check audience
token, err := jwt.ParseSigned(resp.IDToken)
token, err := jwt.ParseSigned(resp.IDToken, []jose.SignatureAlgorithm{jose.RS256})
if err != nil {
t.Fatalf("failed to parse JWT: %v", err)
}
Expand Down Expand Up @@ -1076,7 +1077,7 @@ func TestAZPClaimWithMultipleAudiences(t *testing.T) {
}

// Parse the ID token
token, err := jwt.ParseSigned(tokenResp.IDToken)
token, err := jwt.ParseSigned(tokenResp.IDToken, []jose.SignatureAlgorithm{jose.RS256})
if err != nil {
t.Fatalf("failed to parse JWT: %v", err)
}
Expand All @@ -1092,14 +1093,20 @@ func TestAZPClaimWithMultipleAudiences(t *testing.T) {
t.Fatal("aud claim not found")
}

// The JWT library always serializes audience as an array
audArray, isArray := aud.([]any)
if !isArray {
t.Errorf("expected audience to be array, got %T", aud)
// go-jose/v4 serializes a single-element audience as a string
// per RFC 7519, and multi-element as an array.
var audCount int
switch v := aud.(type) {
case string:
audCount = 1
case []any:
audCount = len(v)
default:
t.Fatalf("unexpected aud type %T", aud)
}

if len(audArray) != tt.expectedAudiences {
t.Errorf("expected %d audiences, got %d", tt.expectedAudiences, len(audArray))
if audCount != tt.expectedAudiences {
t.Errorf("expected %d audiences, got %d", tt.expectedAudiences, audCount)
}

// Check azp claim
Expand Down Expand Up @@ -1337,7 +1344,7 @@ func TestServeToken(t *testing.T) {
t.Fatalf("failed to unmarshal response: %v", err)
}

tok, err := jwt.ParseSigned(resp.IDToken)
tok, err := jwt.ParseSigned(resp.IDToken, []jose.SignatureAlgorithm{jose.RS256})
if err != nil {
t.Fatalf("failed to parse ID token: %v", err)
}
Expand Down