diff --git a/accessjwt/doc.go b/access/jwt/doc.go similarity index 70% rename from accessjwt/doc.go rename to access/jwt/doc.go index 2e323e8..c093404 100644 --- a/accessjwt/doc.go +++ b/access/jwt/doc.go @@ -1,6 +1,6 @@ -// Package accessjwt issues and verifies authkit-owned access JWTs. +// Package jwt issues and verifies authkit-owned access JWTs. // // Access JWTs authenticate an authkit principal. They intentionally carry only // principal identity and token metadata; authorization data stays in authkit // storage and is evaluated at request time. -package accessjwt +package jwt diff --git a/accessjwt/issuer.go b/access/jwt/issuer.go similarity index 79% rename from accessjwt/issuer.go rename to access/jwt/issuer.go index 016df71..79a8eb9 100644 --- a/accessjwt/issuer.go +++ b/access/jwt/issuer.go @@ -1,4 +1,4 @@ -package accessjwt +package jwt import ( "context" @@ -11,7 +11,7 @@ import ( "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" "github.com/lestrrat-go/jwx/v3/jws" - "github.com/lestrrat-go/jwx/v3/jwt" + jwxjwt "github.com/lestrrat-go/jwx/v3/jwt" ) // Issuer issues signed authkit access JWTs. @@ -34,10 +34,10 @@ func NewIssuer(opts IssuerOptions) (*Issuer, error) { return nil, err } if opts.TTL <= 0 { - return nil, errors.New("accessjwt: TTL must be positive") + return nil, errors.New("jwt: TTL must be positive") } if opts.SigningKey == nil { - return nil, errors.New("accessjwt: signing key is required") + return nil, errors.New("jwt: signing key is required") } if err := validateKeyID("signing key", opts.SigningKey); err != nil { return nil, err @@ -82,7 +82,7 @@ func (i *Issuer) IssueToken(ctx context.Context, req IssueRequest) (IssuedToken, tokenID, tokenIDErr := i.tokenID() if tokenIDErr != nil { - return IssuedToken{}, fmt.Errorf("accessjwt: generate token ID: %w", tokenIDErr) + return IssuedToken{}, fmt.Errorf("jwt: generate token ID: %w", tokenIDErr) } if validationErr := validateRequiredString("token ID", tokenID); validationErr != nil { return IssuedToken{}, validationErr @@ -90,7 +90,7 @@ func (i *Issuer) IssueToken(ctx context.Context, req IssueRequest) (IssuedToken, issuedAt := i.clock() expiresAt := issuedAt.Add(i.ttl) - token, err := jwt.NewBuilder(). + token, err := jwxjwt.NewBuilder(). Issuer(i.issuer). Subject(req.PrincipalID). Audience([]string{i.audience}). @@ -99,20 +99,20 @@ func (i *Issuer) IssueToken(ctx context.Context, req IssueRequest) (IssuedToken, JwtID(tokenID). Build() if err != nil { - return IssuedToken{}, fmt.Errorf("accessjwt: build token: %w", err) + return IssuedToken{}, fmt.Errorf("jwt: build token: %w", err) } headers := jws.NewHeaders() if headerErr := headers.Set(jws.TypeKey, TokenType); headerErr != nil { - return IssuedToken{}, fmt.Errorf("accessjwt: set token type: %w", headerErr) + return IssuedToken{}, fmt.Errorf("jwt: set token type: %w", headerErr) } - signed, err := jwt.Sign( + signed, err := jwxjwt.Sign( token, - jwt.WithKey(i.algorithm, i.signingKey, jws.WithProtectedHeaders(headers)), + jwxjwt.WithKey(i.algorithm, i.signingKey, jws.WithProtectedHeaders(headers)), ) if err != nil { - return IssuedToken{}, fmt.Errorf("accessjwt: sign token: %w", err) + return IssuedToken{}, fmt.Errorf("jwt: sign token: %w", err) } return IssuedToken{ @@ -126,10 +126,10 @@ func (i *Issuer) IssueToken(ctx context.Context, req IssueRequest) (IssuedToken, func validateRequiredString(name string, value string) error { if strings.TrimSpace(value) == "" { - return fmt.Errorf("accessjwt: %s is required", name) + return fmt.Errorf("jwt: %s is required", name) } if strings.TrimSpace(value) != value { - return fmt.Errorf("accessjwt: %s must not contain surrounding whitespace", name) + return fmt.Errorf("jwt: %s must not contain surrounding whitespace", name) } return nil diff --git a/accessjwt/accessjwt_test.go b/access/jwt/jwt_test.go similarity index 93% rename from accessjwt/accessjwt_test.go rename to access/jwt/jwt_test.go index 6bd7ee6..ff23a27 100644 --- a/accessjwt/accessjwt_test.go +++ b/access/jwt/jwt_test.go @@ -1,4 +1,4 @@ -package accessjwt +package jwt import ( "context" @@ -12,12 +12,12 @@ import ( "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" "github.com/lestrrat-go/jwx/v3/jws" - "github.com/lestrrat-go/jwx/v3/jwt" + jwxjwt "github.com/lestrrat-go/jwx/v3/jwt" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/roleauth" + "github.com/meigma/authkit/authz/role" "github.com/meigma/authkit/store/memory" ) @@ -298,7 +298,7 @@ func TestVerifiedTokenUsesStorageBackedAuthorization(t *testing.T) { loaded, err := store.FindPrincipal(context.Background(), verified.PrincipalID) require.NoError(t, err) - authorizer, err := roleauth.NewAuthorizer(store) + authorizer, err := role.NewAuthorizer(store) require.NoError(t, err) decision, err := authorizer.Can(context.Background(), authkit.AuthorizationCheck{ Principal: loaded, @@ -416,13 +416,13 @@ func signToken( key := newRSAKey(t, keyID, algorithmName) algorithm, err := signatureAlgorithm(algorithmName) require.NoError(t, err) - token := jwt.New() + token := jwxjwt.New() for name, value := range claims { require.NoError(t, token.Set(name, value)) } headers := jws.NewHeaders() require.NoError(t, headers.Set(jws.TypeKey, tokenType)) - signed, err := jwt.Sign(token, jwt.WithKey(algorithm, key, jws.WithProtectedHeaders(headers))) + signed, err := jwxjwt.Sign(token, jwxjwt.WithKey(algorithm, key, jws.WithProtectedHeaders(headers))) require.NoError(t, err) return string(signed) @@ -438,7 +438,7 @@ func signTokenWithHeaders( algorithm, err := signatureAlgorithm(DefaultAlgorithm) require.NoError(t, err) - token := jwt.New() + token := jwxjwt.New() for name, value := range claims { require.NoError(t, token.Set(name, value)) } @@ -447,7 +447,7 @@ func signTokenWithHeaders( if mutate != nil { mutate(headers) } - signed, err := jwt.Sign(token, jwt.WithKey(algorithm, key, jws.WithProtectedHeaders(headers))) + signed, err := jwxjwt.Sign(token, jwxjwt.WithKey(algorithm, key, jws.WithProtectedHeaders(headers))) require.NoError(t, err) return string(signed) @@ -456,7 +456,7 @@ func signTokenWithHeaders( func signTokenWithoutType(t *testing.T, claims map[string]any) string { t.Helper() - token := jwt.New() + token := jwxjwt.New() for name, value := range claims { require.NoError(t, token.Set(name, value)) } @@ -492,13 +492,13 @@ func hmacSignedToken(t *testing.T, claims map[string]any) string { key, err := jwk.Import([]byte("secret")) require.NoError(t, err) require.NoError(t, key.Set(jwk.KeyIDKey, testKeyID)) - token := jwt.New() + token := jwxjwt.New() for name, value := range claims { require.NoError(t, token.Set(name, value)) } headers := jws.NewHeaders() require.NoError(t, headers.Set(jws.TypeKey, TokenType)) - signed, err := jwt.Sign(token, jwt.WithKey(jwa.HS256(), key, jws.WithProtectedHeaders(headers))) + signed, err := jwxjwt.Sign(token, jwxjwt.WithKey(jwa.HS256(), key, jws.WithProtectedHeaders(headers))) require.NoError(t, err) return string(signed) @@ -508,12 +508,12 @@ func baseClaims() map[string]any { now := fixedTime() return map[string]any{ - jwt.IssuerKey: testIssuer, - jwt.SubjectKey: testPrincipalID, - jwt.AudienceKey: []string{testAudience}, - jwt.IssuedAtKey: now, - jwt.ExpirationKey: now.Add(time.Hour), - jwt.JwtIDKey: testTokenID, + jwxjwt.IssuerKey: testIssuer, + jwxjwt.SubjectKey: testPrincipalID, + jwxjwt.AudienceKey: []string{testAudience}, + jwxjwt.IssuedAtKey: now, + jwxjwt.ExpirationKey: now.Add(time.Hour), + jwxjwt.JwtIDKey: testTokenID, } } @@ -540,21 +540,21 @@ func assertProtectedHeader(t *testing.T, plaintext string, tokenType string, alg func assertNoAuthorizationClaims(t *testing.T, plaintext string, keySet jwk.Set) { t.Helper() - token, err := jwt.Parse( + token, err := jwxjwt.Parse( []byte(plaintext), - jwt.WithKeySet(keySet), - jwt.WithIssuer(testIssuer), - jwt.WithAudience(testAudience), - jwt.WithClock(jwt.ClockFunc(fixedTime)), + jwxjwt.WithKeySet(keySet), + jwxjwt.WithIssuer(testIssuer), + jwxjwt.WithAudience(testAudience), + jwxjwt.WithClock(jwxjwt.ClockFunc(fixedTime)), ) require.NoError(t, err) assert.ElementsMatch(t, []string{ - jwt.AudienceKey, - jwt.ExpirationKey, - jwt.IssuedAtKey, - jwt.IssuerKey, - jwt.JwtIDKey, - jwt.SubjectKey, + jwxjwt.AudienceKey, + jwxjwt.ExpirationKey, + jwxjwt.IssuedAtKey, + jwxjwt.IssuerKey, + jwxjwt.JwtIDKey, + jwxjwt.SubjectKey, }, token.Keys()) assert.False(t, token.Has("roles")) assert.False(t, token.Has("permissions")) diff --git a/accessjwt/keys.go b/access/jwt/keys.go similarity index 78% rename from accessjwt/keys.go rename to access/jwt/keys.go index 05f65cc..91170ea 100644 --- a/accessjwt/keys.go +++ b/access/jwt/keys.go @@ -1,4 +1,4 @@ -package accessjwt +package jwt import ( "errors" @@ -18,7 +18,7 @@ func signatureAlgorithms(names []string) (map[string]jwa.SignatureAlgorithm, err for i, name := range names { algorithm, err := signatureAlgorithm(name) if err != nil { - return nil, fmt.Errorf("accessjwt: allowed algorithm %d: %w", i, err) + return nil, fmt.Errorf("jwt: allowed algorithm %d: %w", i, err) } if _, ok := algorithmMap[algorithm.String()]; ok { continue @@ -54,22 +54,22 @@ func validateKeySet(set jwk.Set, allowed map[string]jwa.SignatureAlgorithm) erro for index := range set.Len() { key, ok := set.Key(index) if !ok || key == nil { - return fmt.Errorf("accessjwt: key set entry %d is required", index) + return fmt.Errorf("jwt: key set entry %d is required", index) } if err := validateKeyID(fmt.Sprintf("key set entry %d", index), key); err != nil { return err } algorithm, ok := key.Algorithm() if !ok { - return fmt.Errorf("accessjwt: key set entry %d algorithm is required", index) + return fmt.Errorf("jwt: key set entry %d algorithm is required", index) } signatureAlgorithm, ok := algorithm.(jwa.SignatureAlgorithm) if !ok { - return fmt.Errorf("accessjwt: key set entry %d algorithm must be a signature algorithm", index) + return fmt.Errorf("jwt: key set entry %d algorithm must be a signature algorithm", index) } if _, ok := allowed[signatureAlgorithm.String()]; !ok { return fmt.Errorf( - "accessjwt: key set entry %d algorithm %q is not allowed", + "jwt: key set entry %d algorithm %q is not allowed", index, signatureAlgorithm.String(), ) @@ -82,10 +82,10 @@ func validateKeySet(set jwk.Set, allowed map[string]jwa.SignatureAlgorithm) erro func validateKeyID(name string, key jwk.Key) error { keyID, ok := key.KeyID() if !ok || strings.TrimSpace(keyID) == "" { - return fmt.Errorf("accessjwt: %s kid is required", name) + return fmt.Errorf("jwt: %s kid is required", name) } if strings.TrimSpace(keyID) != keyID { - return fmt.Errorf("accessjwt: %s kid must not contain surrounding whitespace", name) + return fmt.Errorf("jwt: %s kid must not contain surrounding whitespace", name) } return nil @@ -99,11 +99,11 @@ func validateOptionalKeyAlgorithm(name string, key jwk.Key, expected jwa.Signatu signatureAlgorithm, ok := keyAlgorithm.(jwa.SignatureAlgorithm) if !ok { - return fmt.Errorf("accessjwt: %s algorithm must be a signature algorithm", name) + return fmt.Errorf("jwt: %s algorithm must be a signature algorithm", name) } if signatureAlgorithm.String() != expected.String() { return fmt.Errorf( - "accessjwt: %s algorithm %q does not match %q", + "jwt: %s algorithm %q does not match %q", name, signatureAlgorithm.String(), expected.String(), diff --git a/accessjwt/types.go b/access/jwt/types.go similarity index 99% rename from accessjwt/types.go rename to access/jwt/types.go index 2c7465b..a5a89cf 100644 --- a/accessjwt/types.go +++ b/access/jwt/types.go @@ -1,4 +1,4 @@ -package accessjwt +package jwt import ( "time" diff --git a/accessjwt/verifier.go b/access/jwt/verifier.go similarity index 85% rename from accessjwt/verifier.go rename to access/jwt/verifier.go index 220741a..fa1726d 100644 --- a/accessjwt/verifier.go +++ b/access/jwt/verifier.go @@ -1,4 +1,4 @@ -package accessjwt +package jwt import ( "context" @@ -9,7 +9,7 @@ import ( "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" "github.com/lestrrat-go/jwx/v3/jws" - "github.com/lestrrat-go/jwx/v3/jwt" + jwxjwt "github.com/lestrrat-go/jwx/v3/jwt" "github.com/meigma/authkit" ) @@ -33,10 +33,10 @@ func NewVerifier(opts VerifierOptions) (*Verifier, error) { return nil, err } if opts.KeySet == nil || opts.KeySet.Len() == 0 { - return nil, errors.New("accessjwt: key set is required") + return nil, errors.New("jwt: key set is required") } if opts.AcceptableSkew < 0 { - return nil, errors.New("accessjwt: acceptable skew must not be negative") + return nil, errors.New("jwt: acceptable skew must not be negative") } algorithmMap, err := signatureAlgorithms(opts.AllowedAlgorithms) @@ -49,7 +49,7 @@ func NewVerifier(opts VerifierOptions) (*Verifier, error) { keySet, err := opts.KeySet.Clone() if err != nil { - return nil, fmt.Errorf("accessjwt: clone key set: %w", err) + return nil, fmt.Errorf("jwt: clone key set: %w", err) } clock := opts.Clock @@ -80,17 +80,17 @@ func (v *Verifier) VerifyToken(ctx context.Context, plaintext string) (VerifiedT return VerifiedToken{}, unauthenticated(err.Error()) } - token, err := jwt.Parse( + token, err := jwxjwt.Parse( []byte(plaintext), - jwt.WithKeySet(v.keySet), - jwt.WithIssuer(v.issuer), - jwt.WithAudience(v.audience), - jwt.WithRequiredClaim(jwt.SubjectKey), - jwt.WithRequiredClaim(jwt.JwtIDKey), - jwt.WithRequiredClaim(jwt.IssuedAtKey), - jwt.WithRequiredClaim(jwt.ExpirationKey), - jwt.WithClock(jwt.ClockFunc(v.clock)), - jwt.WithAcceptableSkew(v.acceptableSkew), + jwxjwt.WithKeySet(v.keySet), + jwxjwt.WithIssuer(v.issuer), + jwxjwt.WithAudience(v.audience), + jwxjwt.WithRequiredClaim(jwxjwt.SubjectKey), + jwxjwt.WithRequiredClaim(jwxjwt.JwtIDKey), + jwxjwt.WithRequiredClaim(jwxjwt.IssuedAtKey), + jwxjwt.WithRequiredClaim(jwxjwt.ExpirationKey), + jwxjwt.WithClock(jwxjwt.ClockFunc(v.clock)), + jwxjwt.WithAcceptableSkew(v.acceptableSkew), ) if err != nil { return VerifiedToken{}, unauthenticated("JWT verification failed") @@ -141,7 +141,7 @@ func (v *Verifier) validateProtectedHeaders(raw []byte) error { return nil } -func (v *Verifier) verifiedToken(token jwt.Token) (VerifiedToken, error) { +func (v *Verifier) verifiedToken(token jwxjwt.Token) (VerifiedToken, error) { principalID, ok := token.Subject() if !ok || principalID == "" { return VerifiedToken{}, errors.New("subject claim is required") diff --git a/accessjwtauth/authenticator.go b/access/middleware/authenticator.go similarity index 89% rename from accessjwtauth/authenticator.go rename to access/middleware/authenticator.go index b02474b..13391a1 100644 --- a/accessjwtauth/authenticator.go +++ b/access/middleware/authenticator.go @@ -1,4 +1,4 @@ -package accessjwtauth +package middleware import ( "context" @@ -8,7 +8,7 @@ import ( "strings" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" + "github.com/meigma/authkit/access/jwt" ) const ( @@ -20,20 +20,20 @@ const ( // Authenticator verifies authkit access JWT bearer tokens from HTTP requests. type Authenticator struct { - verifier *accessjwt.Verifier + verifier *jwt.Verifier principalFinder authkit.PrincipalFinder } // NewAuthenticator constructs an access JWT request authenticator. func NewAuthenticator( - verifier *accessjwt.Verifier, + verifier *jwt.Verifier, principalFinder authkit.PrincipalFinder, ) (*Authenticator, error) { if verifier == nil { - return nil, errors.New("accessjwtauth: verifier is required") + return nil, errors.New("middleware: verifier is required") } if principalFinder == nil { - return nil, errors.New("accessjwtauth: principal finder is required") + return nil, errors.New("middleware: principal finder is required") } return &Authenticator{ diff --git a/accessjwtauth/authenticator_test.go b/access/middleware/authenticator_test.go similarity index 82% rename from accessjwtauth/authenticator_test.go rename to access/middleware/authenticator_test.go index bd30e98..d018220 100644 --- a/accessjwtauth/authenticator_test.go +++ b/access/middleware/authenticator_test.go @@ -1,4 +1,4 @@ -package accessjwtauth_test +package middleware_test import ( "context" @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" - "github.com/meigma/authkit/accessjwtauth" + "github.com/meigma/authkit/access/jwt" + "github.com/meigma/authkit/access/middleware" "github.com/meigma/authkit/store/memory" ) @@ -34,7 +34,7 @@ func TestNewAuthenticatorValidatesDependencies(t *testing.T) { tests := []struct { name string - verifier *accessjwt.Verifier + verifier *jwt.Verifier principalFinder authkit.PrincipalFinder }{ { @@ -49,7 +49,7 @@ func TestNewAuthenticatorValidatesDependencies(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - authenticator, err := accessjwtauth.NewAuthenticator(tt.verifier, tt.principalFinder) + authenticator, err := middleware.NewAuthenticator(tt.verifier, tt.principalFinder) require.Error(t, err) assert.Nil(t, authenticator) @@ -65,9 +65,9 @@ func TestAuthenticatorAuthenticatesAccessJWT(t *testing.T) { DisplayName: "notes service", }) require.NoError(t, err) - authenticator, err := accessjwtauth.NewAuthenticator(verifier, store) + authenticator, err := middleware.NewAuthenticator(verifier, store) require.NoError(t, err) - issued, err := issuer.IssueToken(context.Background(), accessjwt.IssueRequest{ + issued, err := issuer.IssueToken(context.Background(), jwt.IssueRequest{ PrincipalID: principal.ID, }) require.NoError(t, err) @@ -76,7 +76,7 @@ func TestAuthenticatorAuthenticatesAccessJWT(t *testing.T) { authentication, err := authenticator.AuthenticatePrincipal(context.Background(), req) require.NoError(t, err) - assert.Equal(t, accessjwtauth.Name, authenticator.Name()) + assert.Equal(t, middleware.Name, authenticator.Name()) require.NotNil(t, authentication) assert.Equal(t, principal, authentication.Principal) } @@ -91,34 +91,34 @@ func TestAuthenticatorRejectsInvalidRequests(t *testing.T) { DisplayName: "notes service", }) require.NoError(t, err) - valid, err := issuer.IssueToken(context.Background(), accessjwt.IssueRequest{ + valid, err := issuer.IssueToken(context.Background(), jwt.IssueRequest{ PrincipalID: principal.ID, }) require.NoError(t, err) expiredIssuer := newIssuer(t, privateKey, fixedTime().Add(-2*time.Hour), nil) - expired, err := expiredIssuer.IssueToken(context.Background(), accessjwt.IssueRequest{ + expired, err := expiredIssuer.IssueToken(context.Background(), jwt.IssueRequest{ PrincipalID: principal.ID, }) require.NoError(t, err) - wrongIssuer := newIssuer(t, privateKey, fixedTime(), func(opts *accessjwt.IssuerOptions) { + wrongIssuer := newIssuer(t, privateKey, fixedTime(), func(opts *jwt.IssuerOptions) { opts.Issuer = "https://other.example.test" }) - wrongIssuerToken, err := wrongIssuer.IssueToken(context.Background(), accessjwt.IssueRequest{ + wrongIssuerToken, err := wrongIssuer.IssueToken(context.Background(), jwt.IssueRequest{ PrincipalID: principal.ID, }) require.NoError(t, err) - wrongAudience := newIssuer(t, privateKey, fixedTime(), func(opts *accessjwt.IssuerOptions) { + wrongAudience := newIssuer(t, privateKey, fixedTime(), func(opts *jwt.IssuerOptions) { opts.Audience = "other-api" }) - wrongAudienceToken, err := wrongAudience.IssueToken(context.Background(), accessjwt.IssueRequest{ + wrongAudienceToken, err := wrongAudience.IssueToken(context.Background(), jwt.IssueRequest{ PrincipalID: principal.ID, }) require.NoError(t, err) - missingPrincipal, err := issuer.IssueToken(context.Background(), accessjwt.IssueRequest{ + missingPrincipal, err := issuer.IssueToken(context.Background(), jwt.IssueRequest{ PrincipalID: "missing", }) require.NoError(t, err) - authenticator, err := accessjwtauth.NewAuthenticator(verifier, store) + authenticator, err := middleware.NewAuthenticator(verifier, store) require.NoError(t, err) tests := []struct { @@ -144,7 +144,7 @@ func TestAuthenticatorRejectsInvalidRequests(t *testing.T) { } } -func newIssuerAndVerifier(t *testing.T) (*accessjwt.Issuer, *accessjwt.Verifier) { +func newIssuerAndVerifier(t *testing.T) (*jwt.Issuer, *jwt.Verifier) { t.Helper() privateKey, publicKey := newRSAKeyPair(t) @@ -155,11 +155,11 @@ func newIssuer( t *testing.T, privateKey jwk.Key, now time.Time, - mutate func(*accessjwt.IssuerOptions), -) *accessjwt.Issuer { + mutate func(*jwt.IssuerOptions), +) *jwt.Issuer { t.Helper() - issuerOpts := accessjwt.IssuerOptions{ + issuerOpts := jwt.IssuerOptions{ Issuer: testIssuer, Audience: testAudience, TTL: time.Hour, @@ -174,18 +174,18 @@ func newIssuer( if mutate != nil { mutate(&issuerOpts) } - issuer, err := accessjwt.NewIssuer(issuerOpts) + issuer, err := jwt.NewIssuer(issuerOpts) require.NoError(t, err) return issuer } -func newVerifier(t *testing.T, publicKey jwk.Key) *accessjwt.Verifier { +func newVerifier(t *testing.T, publicKey jwk.Key) *jwt.Verifier { t.Helper() keySet := jwk.NewSet() require.NoError(t, keySet.AddKey(publicKey)) - verifier, err := accessjwt.NewVerifier(accessjwt.VerifierOptions{ + verifier, err := jwt.NewVerifier(jwt.VerifierOptions{ Issuer: testIssuer, Audience: testAudience, KeySet: keySet, diff --git a/access/middleware/doc.go b/access/middleware/doc.go new file mode 100644 index 0000000..7532fb0 --- /dev/null +++ b/access/middleware/doc.go @@ -0,0 +1,2 @@ +// Package middleware authenticates HTTP bearer requests with authkit access JWTs. +package middleware diff --git a/accessjwtauth/doc.go b/accessjwtauth/doc.go deleted file mode 100644 index eff0093..0000000 --- a/accessjwtauth/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package accessjwtauth authenticates HTTP bearer requests with authkit access JWTs. -package accessjwtauth diff --git a/casbin/authorizer.go b/authz/casbin/authorizer.go similarity index 100% rename from casbin/authorizer.go rename to authz/casbin/authorizer.go diff --git a/casbin/authorizer_test.go b/authz/casbin/authorizer_test.go similarity index 100% rename from casbin/authorizer_test.go rename to authz/casbin/authorizer_test.go diff --git a/casbin/doc.go b/authz/casbin/doc.go similarity index 100% rename from casbin/doc.go rename to authz/casbin/doc.go diff --git a/casbin/options.go b/authz/casbin/options.go similarity index 100% rename from casbin/options.go rename to authz/casbin/options.go diff --git a/roleauth/authorizer.go b/authz/role/authorizer.go similarity index 83% rename from roleauth/authorizer.go rename to authz/role/authorizer.go index 9e3a9ed..c5a1f33 100644 --- a/roleauth/authorizer.go +++ b/authz/role/authorizer.go @@ -1,4 +1,4 @@ -package roleauth +package role import ( "context" @@ -18,7 +18,7 @@ type Authorizer struct { // NewAuthorizer constructs an Authorizer around resolver. func NewAuthorizer(resolver authkit.PrincipalActionResolver) (*Authorizer, error) { if resolver == nil { - return nil, errors.New("roleauth: principal action resolver is required") + return nil, errors.New("role: principal action resolver is required") } return &Authorizer{ @@ -32,10 +32,10 @@ func (a *Authorizer) Can(ctx context.Context, check authkit.AuthorizationCheck) return authkit.Decision{}, err } if check.Principal.ID == "" { - return authkit.Decision{}, errors.New("roleauth: principal ID is required") + return authkit.Decision{}, errors.New("role: principal ID is required") } if check.Action == "" { - return authkit.Decision{}, errors.New("roleauth: action is required") + return authkit.Decision{}, errors.New("role: action is required") } actions, err := a.resolver.ResolvePrincipalActions(ctx, check.Principal.ID) diff --git a/roleauth/authorizer_test.go b/authz/role/authorizer_test.go similarity index 89% rename from roleauth/authorizer_test.go rename to authz/role/authorizer_test.go index 44ea7eb..d98a716 100644 --- a/roleauth/authorizer_test.go +++ b/authz/role/authorizer_test.go @@ -1,4 +1,4 @@ -package roleauth_test +package role_test import ( "context" @@ -11,11 +11,11 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" - "github.com/meigma/authkit/accessjwtauth" - "github.com/meigma/authkit/httpauth" + "github.com/meigma/authkit/access/jwt" + "github.com/meigma/authkit/access/middleware" + "github.com/meigma/authkit/authz/role" + "github.com/meigma/authkit/http/auth" "github.com/meigma/authkit/internal/authtest" - "github.com/meigma/authkit/roleauth" "github.com/meigma/authkit/store/memory" ) @@ -26,7 +26,7 @@ const ( ) func TestNewAuthorizerValidatesResolver(t *testing.T) { - authorizer, err := roleauth.NewAuthorizer(nil) + authorizer, err := role.NewAuthorizer(nil) require.Error(t, err) assert.Nil(t, authorizer) @@ -95,7 +95,7 @@ func TestAuthorizerCan(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - authorizer, err := roleauth.NewAuthorizer(tt.resolver) + authorizer, err := role.NewAuthorizer(tt.resolver) require.NoError(t, err) decision, err := authorizer.Can(context.Background(), tt.check) @@ -110,7 +110,7 @@ func TestAuthorizerCan(t *testing.T) { } func TestAuthorizerRespectsContextCancellation(t *testing.T) { - authorizer, err := roleauth.NewAuthorizer(&fakeActionResolver{actions: []string{testAction}}) + authorizer, err := role.NewAuthorizer(&fakeActionResolver{actions: []string{testAction}}) require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -143,20 +143,20 @@ func TestAuthorizerAllowsHTTPMiddlewareThroughAccessJWT(t *testing.T) { RoleID: testRoleID, })) issuer, verifier := authtest.NewAccessJWTIssuerAndVerifier(t) - issued, err := issuer.IssueToken(ctx, accessjwt.IssueRequest{ + issued, err := issuer.IssueToken(ctx, jwt.IssueRequest{ PrincipalID: principal.ID, }) require.NoError(t, err) - authenticator, err := accessjwtauth.NewAuthenticator(verifier, store) + authenticator, err := middleware.NewAuthenticator(verifier, store) require.NoError(t, err) - authorizer, err := roleauth.NewAuthorizer(store) + authorizer, err := role.NewAuthorizer(store) require.NoError(t, err) pipeline, err := authkit.NewPipeline(authkit.PipelineOptions{ PrincipalAuthenticators: []authkit.PrincipalAuthenticator{authenticator}, Authorizer: authorizer, }) require.NoError(t, err) - middleware, err := httpauth.NewMiddleware(pipeline) + middleware, err := auth.NewMiddleware(pipeline) require.NoError(t, err) handler := middleware.RequireFunc(testAction, func(req *http.Request) (authkit.Resource, error) { return authkit.Resource{ diff --git a/authz/role/doc.go b/authz/role/doc.go new file mode 100644 index 0000000..edc31a3 --- /dev/null +++ b/authz/role/doc.go @@ -0,0 +1,2 @@ +// Package role authorizes requests from local role-derived action grants. +package role diff --git a/compose/doc.go b/compose/doc.go deleted file mode 100644 index 99df854..0000000 --- a/compose/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Package compose provides thin convenience wiring for common authkit setups. -// -// The package is a composition layer over the explicit authkit, accessjwt, -// accessjwtauth, apikey, oidc, and httpauth packages. It does not own storage, -// provider trust, policy setup, migrations, seed credentials, or management -// workflows. -package compose diff --git a/doc.go b/doc.go index db08789..2831a87 100644 --- a/doc.go +++ b/doc.go @@ -6,9 +6,25 @@ // request credentials. External identities are verified and exchanged before a // request reaches protected resource routes. An Authorizer evaluates // authorization checks containing the principal, action, application Resource, -// and caller-supplied Facts. The accessjwt package issues and verifies -// authkit-owned access JWTs, exchange converts verified credentials into access -// JWTs, accessjwtauth adapts access JWTs to HTTP bearer authentication, and -// roleauth authorizes from local admin-managed roles and effective action -// grants. +// and caller-supplied Facts. +// +// Subpackages are organised by role: +// +// - access/jwt — issue and verify authkit-owned access JWTs. +// - access/middleware — adapt access JWTs to HTTP bearer authentication. +// - authz/role — authorize from local admin-managed roles and +// effective action grants. +// - authz/casbin — adapt a Casbin enforcer to authkit.Authorizer. +// - http/auth — net/http middleware atop an authkit.Pipeline. +// - http/facts — opt-in HTTP request fact helpers. +// - http/compose — thin convenience wiring for common setups. +// - proof/oidc — verify trusted OIDC-issued JWT bearer tokens. +// - proof/passkey — WebAuthn passkey registration and login ceremonies. +// - proof/apikey — issue, verify, and revoke opaque API tokens. +// - exchange — trade verified external proof for an access JWT. +// - onboarding — attach identities and provision principals. +// - provisioning — opt-in auto-provisioning during principal resolution. +// - management — service facade for admin setup flows. +// - store/memory — in-memory storage adapter. +// - store/postgres — pgxpool-backed Postgres storage adapter. package authkit diff --git a/docs/docs/explanations/architecture.md b/docs/docs/explanations/architecture.md index d2b58a8..b04aefe 100644 --- a/docs/docs/explanations/architecture.md +++ b/docs/docs/explanations/architecture.md @@ -38,8 +38,8 @@ Authorization receives the resolved principal, an action, a resource, and optional decision-time facts. That shape keeps authorization independent from the credential that authenticated the request. -authkit provides two authorizer adapters today. `roleauth` checks local -role-derived actions. `casbin` projects the same authorization check into an +authkit provides two authorizer adapters today. `authz/role` checks local +role-derived actions. `authz/casbin` projects the same authorization check into an application-owned Casbin model. Both sit behind the same `authkit.Authorizer` port. @@ -50,7 +50,7 @@ action vocabulary they enforce at handlers, such as `note:read`, while administrators create roles, grant actions to roles, and assign principals to roles through application-owned setup paths. -`roleauth` authorizes by resolving the principal's effective action set and +`authz/role` authorizes by resolving the principal's effective action set and checking whether it contains the requested action. It does not derive permissions from external identity metadata, provider groups, or token claims. @@ -84,19 +84,19 @@ code. Adapters sit at the edges: -- `apikey` issues and verifies opaque API tokens. +- `proof/apikey` issues and verifies opaque API tokens. - `exchange` converts verified credentials into access JWTs. -- `accessjwt` issues and verifies authkit-owned access JWTs. -- `accessjwtauth` adapts access JWTs to HTTP bearer authentication. -- `oidc` verifies signed JWT bearer tokens from trusted issuers. +- `access/jwt` issues and verifies authkit-owned access JWTs. +- `access/middleware` adapts access JWTs to HTTP bearer authentication. +- `proof/oidc` verifies signed JWT bearer tokens from trusted issuers. - `onboarding` coordinates explicit identity attachment and principal provisioning. - `provisioning` can create principals for caller-approved unresolved identities. -- `httpauth` adapts a pipeline to `net/http`. -- `httpfacts` provides optional helpers for deriving facts from HTTP requests. -- `roleauth` authorizes from local role-derived effective actions. -- `casbin` adapts Casbin enforcement to the `authkit.Authorizer` port. +- `http/auth` adapts a pipeline to `net/http`. +- `http/facts` provides optional helpers for deriving facts from HTTP requests. +- `authz/role` authorizes from local role-derived effective actions. +- `authz/casbin` adapts Casbin enforcement to the `authkit.Authorizer` port. - `store/memory` and `store/postgres` implement storage contracts. -- `compose` wires common HTTP setups without replacing the lower-level ports. +- `http/compose` wires common HTTP setups without replacing the lower-level ports. ## Identity Linking @@ -151,7 +151,7 @@ boundary. ## HTTP Runtime -`httpauth.Middleware` stores the resolved authentication data in request context. +`auth.Middleware` stores the resolved authentication data in request context. Authorization wrappers extract an authorization request from HTTP request state, then pass the resolved principal, action, resource, and facts to the authorizer. `RequireAuthorization` authenticates before it calls the extractor, so extractors @@ -165,7 +165,7 @@ Default HTTP failure mapping is: - denied authorization decisions -> `403 Forbidden` - unexpected collaborator or extraction failures -> `500 Internal Server Error` -Applications can replace error rendering with `httpauth.WithErrorRenderer`. +Applications can replace error rendering with `auth.WithErrorRenderer`. ## Composition Layers diff --git a/docs/docs/explanations/security-model.md b/docs/docs/explanations/security-model.md index 463efe6..1caa57a 100644 --- a/docs/docs/explanations/security-model.md +++ b/docs/docs/explanations/security-model.md @@ -91,7 +91,7 @@ request data, token claims, or provider-specific groups into authorization facts. Applications choose the facts they trust and pass them explicitly. Local roles are admin-managed and grant action strings to principals through -role membership. The `roleauth` adapter checks only the principal's effective +role membership. The `authz/role` adapter checks only the principal's effective action set; it does not inspect resources, facts, or provider metadata. Initial role assignment from provisioning rules is a bootstrap operation, not a diff --git a/docs/docs/how-to/auto-provision-oidc-principals.md b/docs/docs/how-to/auto-provision-oidc-principals.md index 3ad35ab..1b6e11c 100644 --- a/docs/docs/how-to/auto-provision-oidc-principals.md +++ b/docs/docs/how-to/auto-provision-oidc-principals.md @@ -16,7 +16,7 @@ OIDC JWT -> oidc.Verifier -> authkit.Identity -> exchange.IdentityExchanger -> a ``` Protected resource routes should then accept the authkit access JWT with -`accessjwtauth` or `compose.AccessJWT`. +`access/middleware` or `compose.AccessJWT`. ## Prerequisites diff --git a/docs/docs/how-to/compose-http-auth.md b/docs/docs/how-to/compose-http-auth.md index 7a64125..1c2784c 100644 --- a/docs/docs/how-to/compose-http-auth.md +++ b/docs/docs/how-to/compose-http-auth.md @@ -7,14 +7,14 @@ description: Use compose.NewHTTP to wire authkit for a net/http API service. Use `compose.NewHTTP` when you want the standard `net/http` path with less boilerplate. The helper builds principal authenticators, an `authkit.Pipeline`, and -`httpauth.Middleware`; your application still owns storage, provider trust, +`auth.Middleware`; your application still owns storage, provider trust, local role or Casbin policy setup, and management workflows. ## Prerequisites - A principal finder, such as `store/memory.Store` or `store/postgres.Store` -- An `accessjwt.Verifier` configured for authkit-issued access JWTs -- An authorizer, such as `roleauth.NewAuthorizer` or `casbin.NewAuthorizer` +- An `jwt.Verifier` configured for authkit-issued access JWTs +- An authorizer, such as `role.NewAuthorizer` or `casbin.NewAuthorizer` API tokens are exchange credentials. Keep API-token verification in an application-owned exchange route and protect resource routes with access JWTs. @@ -31,7 +31,7 @@ running the Postgres migrations. ## Configure Access JWT Verification ```go -accessVerifier, err := accessjwt.NewVerifier(accessjwt.VerifierOptions{ +accessVerifier, err := jwt.NewVerifier(jwt.VerifierOptions{ Issuer: "https://auth.example", Audience: "notes-api", KeySet: keySet, @@ -41,15 +41,15 @@ if err != nil { } ``` -Your exchange routes should issue matching tokens with `accessjwt.Issuer`. +Your exchange routes should issue matching tokens with `jwt.Issuer`. ## Configure Authorization For action-only local role checks, grant actions to roles and adapt the store -with `roleauth`: +with `authz/role`: ```go -authorizer, err := roleauth.NewAuthorizer(store) +authorizer, err := role.NewAuthorizer(store) if err != nil { return err } @@ -97,8 +97,8 @@ mux.Handle( ID: req.PathValue("noteID"), }, Facts: authkit.MergeFacts( - httpfacts.Method(req), - httpfacts.Header(req, "X-Tenant-Id"), + facts.Method(req), + facts.Header(req, "X-Tenant-Id"), ), }, nil })(notesHandler), diff --git a/docs/docs/how-to/configure-local-roles.md b/docs/docs/how-to/configure-local-roles.md index 99fdfe0..3cf4502 100644 --- a/docs/docs/how-to/configure-local-roles.md +++ b/docs/docs/how-to/configure-local-roles.md @@ -1,6 +1,6 @@ --- title: How To Configure Local Roles -description: Create local roles, grant actions, assign principals, and authorize with roleauth. +description: Create local roles, grant actions, assign principals, and authorize with role. --- # How To Configure Local Roles @@ -66,10 +66,10 @@ The provided stores make repeated grants and assignments idempotent. ## Build The Role Authorizer -Adapt the store with `roleauth`: +Adapt the store with `authz/role`: ```go -authorizer, err := roleauth.NewAuthorizer(store) +authorizer, err := role.NewAuthorizer(store) if err != nil { return err } diff --git a/docs/docs/how-to/supply-authorization-facts.md b/docs/docs/how-to/supply-authorization-facts.md index cc2ae9f..9b3054d 100644 --- a/docs/docs/how-to/supply-authorization-facts.md +++ b/docs/docs/how-to/supply-authorization-facts.md @@ -11,7 +11,7 @@ principal, action, and resource. ## Prerequisites - An `authkit.Pipeline` -- An `httpauth.Middleware` +- An `auth.Middleware` - An authorizer that uses facts, such as a Casbin adapter with a custom request builder @@ -42,13 +42,13 @@ request context when it needs to load application-owned resource state. ## Merge HTTP Facts -Use `httpfacts` helpers for common request values: +Use `http/facts` helpers for common request values: ```go facts := authkit.MergeFacts( - httpfacts.Method(req), - httpfacts.PathValue(req, "tenantID"), - httpfacts.Header(req, "X-Request-Source"), + facts.Method(req), + facts.PathValue(req, "tenantID"), + facts.Header(req, "X-Request-Source"), authkit.Facts{ "resource.owner_id": note.OwnerID, }, @@ -63,7 +63,7 @@ Load app-owned facts only after the request is authenticated: ```go func extractNoteAuthorization(req *http.Request) (authkit.AuthorizationRequest, error) { - authentication, ok := httpauth.AuthenticationFromContext(req.Context()) + authentication, ok := auth.AuthenticationFromContext(req.Context()) if !ok { return authkit.AuthorizationRequest{}, errors.New("missing authentication") } diff --git a/docs/docs/how-to/use-explicit-composition.md b/docs/docs/how-to/use-explicit-composition.md index d4faf52..80c7dae 100644 --- a/docs/docs/how-to/use-explicit-composition.md +++ b/docs/docs/how-to/use-explicit-composition.md @@ -11,7 +11,7 @@ construction, ordering, middleware options, or non-standard runtime wiring. ## Build Principal Authenticators ```go -accessAuthenticator, err := accessjwtauth.NewAuthenticator(accessVerifier, principalFinder) +accessAuthenticator, err := middleware.NewAuthenticator(accessVerifier, principalFinder) if err != nil { return err } @@ -42,9 +42,9 @@ action, resource, and optional facts. ## Build HTTP Middleware ```go -middleware, err := httpauth.NewMiddleware( +middleware, err := auth.NewMiddleware( pipeline, - httpauth.WithErrorRenderer(customRenderer), + auth.WithErrorRenderer(customRenderer), ) if err != nil { return err diff --git a/docs/docs/reference/extension-points.md b/docs/docs/reference/extension-points.md index 9dbcd33..b2ecfa3 100644 --- a/docs/docs/reference/extension-points.md +++ b/docs/docs/reference/extension-points.md @@ -22,7 +22,7 @@ resource middleware. Provided adapters: -- `accessjwtauth.NewAuthenticator` +- `middleware.NewAuthenticator` ### `authkit.PrincipalResolver` @@ -56,7 +56,7 @@ Implement this for a policy engine other than Casbin. Provided adapters: -- `roleauth.NewAuthorizer` +- `role.NewAuthorizer` - `casbin.NewAuthorizer` ## Management Ports @@ -165,19 +165,19 @@ Provided sources: ## HTTP Adapter -`httpauth.WithErrorRenderer` replaces the default HTTP error rendering. Use it +`auth.WithErrorRenderer` replaces the default HTTP error rendering. Use it when an API needs JSON errors, custom status bodies, or structured error responses. -`httpauth.AuthorizationExtractor` lets a route map request state to an +`auth.AuthorizationExtractor` lets a route map request state to an `authkit.AuthorizationRequest` before authorization. Use it when a route needs to supply decision-time facts. The extractor receives a request whose context already contains the resolved `authkit.Authentication`. -`httpauth.ResourceExtractor` remains available for routes that only need to map +`auth.ResourceExtractor` remains available for routes that only need to map request state to an `authkit.Resource`. -The `httpfacts` package provides optional helpers for deriving method, host, +The `http/facts` package provides optional helpers for deriving method, host, path, remote address, selected header, and path-value facts from HTTP requests. These helpers do not inject facts automatically. @@ -190,7 +190,7 @@ attribute shape. ## Local Role Adapter -`roleauth.NewAuthorizer` checks whether the resolved principal has the requested +`role.NewAuthorizer` checks whether the resolved principal has the requested `authkit.AuthorizationCheck.Action` through admin-managed local role grants. It does not inspect resource metadata, facts, or external provider claims. @@ -200,7 +200,7 @@ For setup steps, see [How to configure local roles](../how-to/configure-local-ro `compose.NewHTTP` wires common `net/http` setups. It builds principal authenticators in the order supplied, then constructs an `authkit.Pipeline` and -`httpauth.Middleware`. +`auth.Middleware`. Use direct composition instead when you need complete control over authenticator construction or middleware setup. diff --git a/exchange/apitoken.go b/exchange/apitoken.go index 5dbaf5c..c7fa4d2 100644 --- a/exchange/apitoken.go +++ b/exchange/apitoken.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" + "github.com/meigma/authkit/access/jwt" ) // APITokenExchanger exchanges opaque API tokens for authkit access JWTs. @@ -54,7 +54,7 @@ func (e *APITokenExchanger) Exchange(ctx context.Context, req APITokenRequest) ( return APITokenResult{}, exchangeError("find principal", err) } - accessToken, err := e.accessTokens.IssueToken(ctx, accessjwt.IssueRequest{ + accessToken, err := e.accessTokens.IssueToken(ctx, jwt.IssueRequest{ PrincipalID: principal.ID, }) if err != nil { diff --git a/exchange/apitoken_test.go b/exchange/apitoken_test.go index c6ab522..c1be904 100644 --- a/exchange/apitoken_test.go +++ b/exchange/apitoken_test.go @@ -10,10 +10,10 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/access/jwt" "github.com/meigma/authkit/exchange" "github.com/meigma/authkit/internal/authtest" + "github.com/meigma/authkit/proof/apikey" "github.com/meigma/authkit/store/memory" ) @@ -269,7 +269,7 @@ func newAPITokenExchanger(t *testing.T, opts exchange.APITokenOptions) *exchange return exchanger } -func newAccessJWTIssuerAndVerifier(t *testing.T) (*accessjwt.Issuer, *accessjwt.Verifier) { +func newAccessJWTIssuerAndVerifier(t *testing.T) (*jwt.Issuer, *jwt.Verifier) { t.Helper() return authtest.NewAccessJWTIssuerAndVerifier( @@ -305,14 +305,14 @@ func (f fakePrincipalFinder) FindPrincipal( } type fakeAccessTokenIssuer struct { - token accessjwt.IssuedToken + token jwt.IssuedToken err error } func (f fakeAccessTokenIssuer) IssueToken( context.Context, - accessjwt.IssueRequest, -) (accessjwt.IssuedToken, error) { + jwt.IssueRequest, +) (jwt.IssuedToken, error) { return f.token, f.err } diff --git a/exchange/identity.go b/exchange/identity.go index e2f3b15..3da41bd 100644 --- a/exchange/identity.go +++ b/exchange/identity.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" + "github.com/meigma/authkit/access/jwt" ) // IdentityExchanger exchanges verified external identities for authkit access JWTs. @@ -47,7 +47,7 @@ func (e *IdentityExchanger) Exchange(ctx context.Context, req IdentityRequest) ( return IdentityResult{}, fmt.Errorf("%w: resolved principal ID is required", authkit.ErrInternal) } - accessToken, err := e.accessTokens.IssueToken(ctx, accessjwt.IssueRequest{ + accessToken, err := e.accessTokens.IssueToken(ctx, jwt.IssueRequest{ PrincipalID: principal.ID, }) if err != nil { diff --git a/exchange/identity_test.go b/exchange/identity_test.go index db412a8..579af4a 100644 --- a/exchange/identity_test.go +++ b/exchange/identity_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" + "github.com/meigma/authkit/access/jwt" "github.com/meigma/authkit/exchange" ) @@ -49,7 +49,7 @@ func TestNewIdentityExchangerValidatesDependencies(t *testing.T) { func TestIdentityExchangerExchangesResolvedIdentityForAccessJWT(t *testing.T) { identity := testExchangeIdentity() principal := testExchangePrincipal() - accessToken := accessjwt.IssuedToken{ + accessToken := jwt.IssuedToken{ ID: testTokenID, PrincipalID: principal.ID, Plaintext: "access.jwt", diff --git a/exchange/types.go b/exchange/types.go index a1b6333..074e762 100644 --- a/exchange/types.go +++ b/exchange/types.go @@ -4,8 +4,8 @@ import ( "context" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/access/jwt" + "github.com/meigma/authkit/proof/apikey" ) // APITokenVerifier verifies opaque API tokens. @@ -17,7 +17,7 @@ type APITokenVerifier interface { // AccessTokenIssuer issues authkit access JWTs. type AccessTokenIssuer interface { // IssueToken issues an access JWT for req.PrincipalID. - IssueToken(ctx context.Context, req accessjwt.IssueRequest) (accessjwt.IssuedToken, error) + IssueToken(ctx context.Context, req jwt.IssueRequest) (jwt.IssuedToken, error) } // APITokenOptions configures an APITokenExchanger. @@ -47,7 +47,7 @@ type APITokenResult struct { Principal authkit.Principal // AccessToken is the authkit access JWT issued for Principal. - AccessToken accessjwt.IssuedToken + AccessToken jwt.IssuedToken } // IdentityOptions configures an IdentityExchanger. @@ -74,5 +74,5 @@ type IdentityResult struct { Principal authkit.Principal // AccessToken is the authkit access JWT issued for Principal. - AccessToken accessjwt.IssuedToken + AccessToken jwt.IssuedToken } diff --git a/httpauth/context.go b/http/auth/context.go similarity index 98% rename from httpauth/context.go rename to http/auth/context.go index 8f8fe30..cea3360 100644 --- a/httpauth/context.go +++ b/http/auth/context.go @@ -1,4 +1,4 @@ -package httpauth +package auth import ( "context" diff --git a/httpauth/doc.go b/http/auth/doc.go similarity index 83% rename from httpauth/doc.go rename to http/auth/doc.go index b1ec442..482bc11 100644 --- a/httpauth/doc.go +++ b/http/auth/doc.go @@ -1,4 +1,4 @@ -// Package httpauth adapts authkit pipelines to net/http handlers. +// Package auth adapts authkit pipelines to net/http handlers. // // The default renderer maps missing or invalid credentials and unresolved // identities to HTTP 401, denied authorization decisions to HTTP 403, and @@ -8,4 +8,4 @@ // RequireAuthorization authenticates first, stores authentication data in the // request context, and then lets applications supply per-request authorization // facts. -package httpauth +package auth diff --git a/httpauth/middleware.go b/http/auth/middleware.go similarity index 98% rename from httpauth/middleware.go rename to http/auth/middleware.go index c2846cc..d8482b2 100644 --- a/httpauth/middleware.go +++ b/http/auth/middleware.go @@ -1,4 +1,4 @@ -package httpauth +package auth import ( "errors" @@ -26,7 +26,7 @@ type Middleware struct { // NewMiddleware constructs HTTP middleware around pipeline. func NewMiddleware(pipeline *authkit.Pipeline, opts ...Option) (*Middleware, error) { if pipeline == nil { - return nil, errors.New("httpauth: pipeline is required") + return nil, errors.New("auth: pipeline is required") } cfg := defaultOptions() diff --git a/httpauth/middleware_test.go b/http/auth/middleware_test.go similarity index 95% rename from httpauth/middleware_test.go rename to http/auth/middleware_test.go index fd10d33..189facc 100644 --- a/httpauth/middleware_test.go +++ b/http/auth/middleware_test.go @@ -1,4 +1,4 @@ -package httpauth_test +package auth_test import ( "context" @@ -12,22 +12,22 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/httpauth" + "github.com/meigma/authkit/http/auth" ) func TestNewMiddlewareValidatesPipeline(t *testing.T) { - middleware, err := httpauth.NewMiddleware(nil) + middleware, err := auth.NewMiddleware(nil) require.Error(t, err) assert.Nil(t, middleware) } func TestContextHelpersReturnFalseWhenMissing(t *testing.T) { - authentication, ok := httpauth.AuthenticationFromContext(context.Background()) + authentication, ok := auth.AuthenticationFromContext(context.Background()) assert.False(t, ok) assert.Empty(t, authentication) - principal, ok := httpauth.PrincipalFromContext(context.Background()) + principal, ok := auth.PrincipalFromContext(context.Background()) assert.False(t, ok) assert.Empty(t, principal) } @@ -254,9 +254,9 @@ func TestMiddlewareRendersInternalFailures(t *testing.T) { func TestMiddlewareUsesCustomRenderer(t *testing.T) { var renderedErr error pipeline := newTestPipelineWithPrincipalAuthenticator(t, denyPrincipalAuthenticator("test"), allowAuthorizer()) - middleware, err := httpauth.NewMiddleware( + middleware, err := auth.NewMiddleware( pipeline, - httpauth.WithErrorRenderer(func(w http.ResponseWriter, _ *http.Request, err error) { + auth.WithErrorRenderer(func(w http.ResponseWriter, _ *http.Request, err error) { renderedErr = err http.Error(w, "custom", http.StatusTeapot) }), @@ -274,10 +274,10 @@ func TestMiddlewareUsesCustomRenderer(t *testing.T) { assert.Equal(t, "custom\n", recorder.Body.String()) } -func newMiddleware(t *testing.T, pipeline *authkit.Pipeline) *httpauth.Middleware { +func newMiddleware(t *testing.T, pipeline *authkit.Pipeline) *auth.Middleware { t.Helper() - middleware, err := httpauth.NewMiddleware(pipeline) + middleware, err := auth.NewMiddleware(pipeline) require.NoError(t, err) return middleware @@ -327,11 +327,11 @@ func newTestPipelineWithOptions(t *testing.T, opts authkit.PipelineOptions) *aut func assertAuthenticationContext(ctx context.Context, t *testing.T) { t.Helper() - authentication, ok := httpauth.AuthenticationFromContext(ctx) + authentication, ok := auth.AuthenticationFromContext(ctx) require.True(t, ok) assert.Equal(t, testAuthentication(), authentication) - principal, ok := httpauth.PrincipalFromContext(ctx) + principal, ok := auth.PrincipalFromContext(ctx) require.True(t, ok) assert.Equal(t, testPrincipal(), principal) } diff --git a/httpauth/options.go b/http/auth/options.go similarity index 95% rename from httpauth/options.go rename to http/auth/options.go index 2e1ba5a..59c20fc 100644 --- a/httpauth/options.go +++ b/http/auth/options.go @@ -1,4 +1,4 @@ -package httpauth +package auth type options struct { renderer ErrorRenderer diff --git a/compose/authenticators.go b/http/compose/authenticators.go similarity index 79% rename from compose/authenticators.go rename to http/compose/authenticators.go index 9ca2d29..1350dc0 100644 --- a/compose/authenticators.go +++ b/http/compose/authenticators.go @@ -2,8 +2,8 @@ package compose import ( "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" - "github.com/meigma/authkit/accessjwtauth" + "github.com/meigma/authkit/access/jwt" + "github.com/meigma/authkit/access/middleware" ) // PrincipalAuthenticatorSpec builds one authkit principal authenticator for a composed service. @@ -13,13 +13,13 @@ type PrincipalAuthenticatorSpec interface { } type accessJWTAuthenticatorSpec struct { - verifier *accessjwt.Verifier + verifier *jwt.Verifier principalFinder authkit.PrincipalFinder } // AccessJWT configures an access JWT authenticator from verifier and principalFinder. func AccessJWT( - verifier *accessjwt.Verifier, + verifier *jwt.Verifier, principalFinder authkit.PrincipalFinder, ) PrincipalAuthenticatorSpec { return accessJWTAuthenticatorSpec{ @@ -29,5 +29,5 @@ func AccessJWT( } func (s accessJWTAuthenticatorSpec) BuildPrincipalAuthenticator() (authkit.PrincipalAuthenticator, error) { - return accessjwtauth.NewAuthenticator(s.verifier, s.principalFinder) + return middleware.NewAuthenticator(s.verifier, s.principalFinder) } diff --git a/http/compose/doc.go b/http/compose/doc.go new file mode 100644 index 0000000..787e03b --- /dev/null +++ b/http/compose/doc.go @@ -0,0 +1,7 @@ +// Package compose provides thin convenience wiring for common authkit setups. +// +// The package is a composition layer over the explicit authkit, access/jwt, +// access/middleware, proof/apikey, proof/oidc, and http/auth packages. It does +// not own storage, provider trust, policy setup, migrations, seed credentials, +// or management workflows. +package compose diff --git a/compose/http.go b/http/compose/http.go similarity index 92% rename from compose/http.go rename to http/compose/http.go index 2ffe4c3..27930a5 100644 --- a/compose/http.go +++ b/http/compose/http.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/meigma/authkit" - "github.com/meigma/authkit/httpauth" + "github.com/meigma/authkit/http/auth" ) // HTTPOptions configures HTTP auth composition. @@ -17,7 +17,7 @@ type HTTPOptions struct { Authorizer authkit.Authorizer // MiddlewareOptions configure the generated httpauth middleware. - MiddlewareOptions []httpauth.Option + MiddlewareOptions []auth.Option } // HTTP is a composed authkit HTTP setup. @@ -26,7 +26,7 @@ type HTTP struct { Pipeline *authkit.Pipeline // Middleware adapts Pipeline to net/http handlers. - Middleware *httpauth.Middleware + Middleware *auth.Middleware } // NewHTTP composes authenticators, a pipeline, and net/http middleware. @@ -47,7 +47,7 @@ func NewHTTP(opts HTTPOptions) (*HTTP, error) { return nil, fmt.Errorf("compose: create pipeline: %w", err) } - middleware, err := httpauth.NewMiddleware(pipeline, opts.MiddlewareOptions...) + middleware, err := auth.NewMiddleware(pipeline, opts.MiddlewareOptions...) if err != nil { return nil, fmt.Errorf("compose: create HTTP middleware: %w", err) } diff --git a/compose/http_test.go b/http/compose/http_test.go similarity index 92% rename from compose/http_test.go rename to http/compose/http_test.go index 34831c2..338c24a 100644 --- a/compose/http_test.go +++ b/http/compose/http_test.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" - "github.com/meigma/authkit/compose" - "github.com/meigma/authkit/httpauth" + "github.com/meigma/authkit/access/jwt" + "github.com/meigma/authkit/http/auth" + "github.com/meigma/authkit/http/compose" "github.com/meigma/authkit/internal/authtest" "github.com/meigma/authkit/store/memory" ) @@ -103,7 +103,7 @@ func TestNewHTTPWithAccessJWTAuthenticatesPrincipals(t *testing.T) { }) require.NoError(t, err) issuer, verifier := newAccessJWTIssuerAndVerifier(t) - issued, err := issuer.IssueToken(ctx, accessjwt.IssueRequest{ + issued, err := issuer.IssueToken(ctx, jwt.IssueRequest{ PrincipalID: principal.ID, }) require.NoError(t, err) @@ -163,7 +163,7 @@ func TestNewHTTPReturnsUsableMiddleware(t *testing.T) { var principal authkit.Principal var ok bool handler := kit.Middleware.Authenticate(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - principal, ok = httpauth.PrincipalFromContext(req.Context()) + principal, ok = auth.PrincipalFromContext(req.Context()) _, _ = w.Write([]byte(principal.ID)) })) @@ -184,8 +184,8 @@ func TestNewHTTPAppliesMiddlewareOptions(t *testing.T) { }), }, Authorizer: testAuthorizer{}, - MiddlewareOptions: []httpauth.Option{ - httpauth.WithErrorRenderer(func(w http.ResponseWriter, _ *http.Request, _ error) { + MiddlewareOptions: []auth.Option{ + auth.WithErrorRenderer(func(w http.ResponseWriter, _ *http.Request, _ error) { http.Error(w, "custom auth error", http.StatusTeapot) }), }, @@ -215,12 +215,12 @@ func TestAccessJWTSpecWrapsConstructorErrors(t *testing.T) { { name: "verifier is required", spec: compose.AccessJWT(nil, store), - want: "compose: build principal authenticator 0: accessjwtauth: verifier is required", + want: "compose: build principal authenticator 0: middleware: verifier is required", }, { name: "principal finder is required", spec: compose.AccessJWT(verifier, nil), - want: "compose: build principal authenticator 0: accessjwtauth: principal finder is required", + want: "compose: build principal authenticator 0: middleware: principal finder is required", }, } @@ -292,7 +292,7 @@ func requestWithBearer(token string) *http.Request { return req } -func newAccessJWTIssuerAndVerifier(t *testing.T) (*accessjwt.Issuer, *accessjwt.Verifier) { +func newAccessJWTIssuerAndVerifier(t *testing.T) (*jwt.Issuer, *jwt.Verifier) { t.Helper() return authtest.NewAccessJWTIssuerAndVerifier(t) diff --git a/httpfacts/facts.go b/http/facts/facts.go similarity index 95% rename from httpfacts/facts.go rename to http/facts/facts.go index 47d1cf0..db47c18 100644 --- a/httpfacts/facts.go +++ b/http/facts/facts.go @@ -1,6 +1,6 @@ -// Package httpfacts provides opt-in helpers for deriving authorization facts +// Package facts provides opt-in helpers for deriving authorization facts // from net/http requests. -package httpfacts +package facts import ( "net/http" diff --git a/http/facts/facts_test.go b/http/facts/facts_test.go new file mode 100644 index 0000000..85bb1bd --- /dev/null +++ b/http/facts/facts_test.go @@ -0,0 +1,54 @@ +package facts_test + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/meigma/authkit" + "github.com/meigma/authkit/http/facts" +) + +func TestRequestFactHelpers(t *testing.T) { + req := httptest.NewRequest(http.MethodPost, "https://api.example.test/images/123", nil) + req.Host = "api.example.test" + req.RemoteAddr = "192.0.2.10:12345" + req.Header.Set("X-Tenant-Id", "tenant-1") + req.SetPathValue("imageID", "123") + + got := authkit.MergeFacts( + facts.Method(req), + facts.Host(req), + facts.Path(req), + facts.RemoteAddr(req), + facts.Header(req, "X-Tenant-Id"), + facts.PathValue(req, "imageID"), + ) + + assert.Equal(t, authkit.Facts{ + facts.MethodKey: http.MethodPost, + facts.HostKey: "api.example.test", + facts.PathKey: "/images/123", + facts.RemoteAddrKey: "192.0.2.10:12345", + facts.HeaderKey("X-Tenant-Id"): "tenant-1", + facts.PathValueKey("imageID"): "123", + }, got) +} + +func TestHelpersReturnNilForMissingRequest(t *testing.T) { + assert.Nil(t, facts.Method(nil)) + assert.Nil(t, facts.Host(nil)) + assert.Nil(t, facts.Path(nil)) + assert.Nil(t, facts.RemoteAddr(nil)) + assert.Nil(t, facts.Header(nil, "X-Tenant-Id")) + assert.Nil(t, facts.PathValue(nil, "imageID")) +} + +func TestHelpersReturnNilForMissingNames(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/", nil) + + assert.Nil(t, facts.Header(req, "")) + assert.Nil(t, facts.PathValue(req, "")) +} diff --git a/httpfacts/facts_test.go b/httpfacts/facts_test.go deleted file mode 100644 index 7b0c6bb..0000000 --- a/httpfacts/facts_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package httpfacts_test - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/meigma/authkit" - "github.com/meigma/authkit/httpfacts" -) - -func TestRequestFactHelpers(t *testing.T) { - req := httptest.NewRequest(http.MethodPost, "https://api.example.test/images/123", nil) - req.Host = "api.example.test" - req.RemoteAddr = "192.0.2.10:12345" - req.Header.Set("X-Tenant-Id", "tenant-1") - req.SetPathValue("imageID", "123") - - facts := authkit.MergeFacts( - httpfacts.Method(req), - httpfacts.Host(req), - httpfacts.Path(req), - httpfacts.RemoteAddr(req), - httpfacts.Header(req, "X-Tenant-Id"), - httpfacts.PathValue(req, "imageID"), - ) - - assert.Equal(t, authkit.Facts{ - httpfacts.MethodKey: http.MethodPost, - httpfacts.HostKey: "api.example.test", - httpfacts.PathKey: "/images/123", - httpfacts.RemoteAddrKey: "192.0.2.10:12345", - httpfacts.HeaderKey("X-Tenant-Id"): "tenant-1", - httpfacts.PathValueKey("imageID"): "123", - }, facts) -} - -func TestHelpersReturnNilForMissingRequest(t *testing.T) { - assert.Nil(t, httpfacts.Method(nil)) - assert.Nil(t, httpfacts.Host(nil)) - assert.Nil(t, httpfacts.Path(nil)) - assert.Nil(t, httpfacts.RemoteAddr(nil)) - assert.Nil(t, httpfacts.Header(nil, "X-Tenant-Id")) - assert.Nil(t, httpfacts.PathValue(nil, "imageID")) -} - -func TestHelpersReturnNilForMissingNames(t *testing.T) { - req := httptest.NewRequest(http.MethodGet, "/", nil) - - assert.Nil(t, httpfacts.Header(req, "")) - assert.Nil(t, httpfacts.PathValue(req, "")) -} diff --git a/internal/authtest/accessjwt.go b/internal/authtest/accessjwt.go index bb5e64f..f51853b 100644 --- a/internal/authtest/accessjwt.go +++ b/internal/authtest/accessjwt.go @@ -10,7 +10,7 @@ import ( "github.com/lestrrat-go/jwx/v3/jwk" "github.com/stretchr/testify/require" - "github.com/meigma/authkit/accessjwt" + "github.com/meigma/authkit/access/jwt" ) const ( @@ -53,7 +53,7 @@ func WithAccessJWTTokenID(tokenID func() (string, error)) AccessJWTOption { func NewAccessJWTIssuerAndVerifier( t testing.TB, opts ...AccessJWTOption, -) (*accessjwt.Issuer, *accessjwt.Verifier) { +) (*jwt.Issuer, *jwt.Verifier) { t.Helper() cfg := accessJWTConfig{ @@ -79,7 +79,7 @@ func NewAccessJWTIssuerAndVerifier( keySet := jwk.NewSet() require.NoError(t, keySet.AddKey(publicKey)) - issuer, err := accessjwt.NewIssuer(accessjwt.IssuerOptions{ + issuer, err := jwt.NewIssuer(jwt.IssuerOptions{ Issuer: cfg.issuer, Audience: cfg.audience, TTL: time.Hour, @@ -88,7 +88,7 @@ func NewAccessJWTIssuerAndVerifier( TokenID: cfg.tokenID, }) require.NoError(t, err) - verifier, err := accessjwt.NewVerifier(accessjwt.VerifierOptions{ + verifier, err := jwt.NewVerifier(jwt.VerifierOptions{ Issuer: cfg.issuer, Audience: cfg.audience, KeySet: keySet, diff --git a/internal/storetest/fixtures.go b/internal/storetest/fixtures.go index f9d03f0..a1806ce 100644 --- a/internal/storetest/fixtures.go +++ b/internal/storetest/fixtures.go @@ -11,9 +11,9 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" - "github.com/meigma/authkit/oidc" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/apikey" + "github.com/meigma/authkit/proof/oidc" + "github.com/meigma/authkit/proof/passkey" ) // createPrincipal creates a user principal with the standard test display name diff --git a/internal/storetest/oidc.go b/internal/storetest/oidc.go index 697531a..a680fb0 100644 --- a/internal/storetest/oidc.go +++ b/internal/storetest/oidc.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) // runOIDCSuite exercises trusted OIDC provider storage including upsert, diff --git a/internal/storetest/passkey.go b/internal/storetest/passkey.go index 540d1e8..2ba680c 100644 --- a/internal/storetest/passkey.go +++ b/internal/storetest/passkey.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" ) // runPasskeySuite exercises passkey user and credential storage including diff --git a/internal/storetest/storetest.go b/internal/storetest/storetest.go index 22bb855..262d946 100644 --- a/internal/storetest/storetest.go +++ b/internal/storetest/storetest.go @@ -9,9 +9,9 @@ import ( "time" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" - "github.com/meigma/authkit/oidc" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/apikey" + "github.com/meigma/authkit/proof/oidc" + "github.com/meigma/authkit/proof/passkey" ) const ( diff --git a/internal/storetest/tokens.go b/internal/storetest/tokens.go index 5132763..b216e57 100644 --- a/internal/storetest/tokens.go +++ b/internal/storetest/tokens.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/proof/apikey" ) // runTokenSuite exercises API token storage including create, find, last-used diff --git a/management/service.go b/management/service.go index 5d583a9..ff6780f 100644 --- a/management/service.go +++ b/management/service.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/proof/apikey" ) // APITokens issues and revokes opaque API tokens. diff --git a/management/service_test.go b/management/service_test.go index 34affe3..032efb2 100644 --- a/management/service_test.go +++ b/management/service_test.go @@ -10,8 +10,8 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" "github.com/meigma/authkit/management" + "github.com/meigma/authkit/proof/apikey" "github.com/meigma/authkit/store/memory" ) diff --git a/apikey/doc.go b/proof/apikey/doc.go similarity index 100% rename from apikey/doc.go rename to proof/apikey/doc.go diff --git a/apikey/errors.go b/proof/apikey/errors.go similarity index 100% rename from apikey/errors.go rename to proof/apikey/errors.go diff --git a/apikey/options.go b/proof/apikey/options.go similarity index 100% rename from apikey/options.go rename to proof/apikey/options.go diff --git a/apikey/service.go b/proof/apikey/service.go similarity index 100% rename from apikey/service.go rename to proof/apikey/service.go diff --git a/apikey/service_test.go b/proof/apikey/service_test.go similarity index 99% rename from apikey/service_test.go rename to proof/apikey/service_test.go index 22a9978..ef3bd45 100644 --- a/apikey/service_test.go +++ b/proof/apikey/service_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/proof/apikey" "github.com/meigma/authkit/store/memory" ) diff --git a/apikey/store.go b/proof/apikey/store.go similarity index 100% rename from apikey/store.go rename to proof/apikey/store.go diff --git a/apikey/types.go b/proof/apikey/types.go similarity index 100% rename from apikey/types.go rename to proof/apikey/types.go diff --git a/oidc/doc.go b/proof/oidc/doc.go similarity index 100% rename from oidc/doc.go rename to proof/oidc/doc.go diff --git a/oidc/options.go b/proof/oidc/options.go similarity index 100% rename from oidc/options.go rename to proof/oidc/options.go diff --git a/oidc/source.go b/proof/oidc/source.go similarity index 100% rename from oidc/source.go rename to proof/oidc/source.go diff --git a/oidc/types.go b/proof/oidc/types.go similarity index 100% rename from oidc/types.go rename to proof/oidc/types.go diff --git a/oidc/verifier.go b/proof/oidc/verifier.go similarity index 100% rename from oidc/verifier.go rename to proof/oidc/verifier.go diff --git a/oidc/verifier_test.go b/proof/oidc/verifier_test.go similarity index 99% rename from oidc/verifier_test.go rename to proof/oidc/verifier_test.go index a767797..62371e7 100644 --- a/oidc/verifier_test.go +++ b/proof/oidc/verifier_test.go @@ -18,7 +18,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - authkitoidc "github.com/meigma/authkit/oidc" + authkitoidc "github.com/meigma/authkit/proof/oidc" ) const ( diff --git a/passkey/clone.go b/proof/passkey/clone.go similarity index 100% rename from passkey/clone.go rename to proof/passkey/clone.go diff --git a/passkey/doc.go b/proof/passkey/doc.go similarity index 87% rename from passkey/doc.go rename to proof/passkey/doc.go index c028cd7..17e242a 100644 --- a/passkey/doc.go +++ b/proof/passkey/doc.go @@ -5,5 +5,5 @@ // use the returned WebAuthn options and session data in their own transport // layer, then exchange verified identities through authkit's onboarding or // exchange packages. For reusable server-side session storage between begin and -// finish calls, see github.com/meigma/authkit/passkey/session. +// finish calls, see github.com/meigma/authkit/proof/passkey/session. package passkey diff --git a/passkey/errors.go b/proof/passkey/errors.go similarity index 100% rename from passkey/errors.go rename to proof/passkey/errors.go diff --git a/passkey/service.go b/proof/passkey/service.go similarity index 100% rename from passkey/service.go rename to proof/passkey/service.go diff --git a/passkey/service_test.go b/proof/passkey/service_test.go similarity index 100% rename from passkey/service_test.go rename to proof/passkey/service_test.go diff --git a/passkey/session/clone.go b/proof/passkey/session/clone.go similarity index 98% rename from passkey/session/clone.go rename to proof/passkey/session/clone.go index de004f8..272adea 100644 --- a/passkey/session/clone.go +++ b/proof/passkey/session/clone.go @@ -4,7 +4,7 @@ import ( "github.com/go-webauthn/webauthn/protocol" "github.com/go-webauthn/webauthn/webauthn" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" ) func cloneRegistration(registration Registration) Registration { diff --git a/passkey/session/doc.go b/proof/passkey/session/doc.go similarity index 100% rename from passkey/session/doc.go rename to proof/passkey/session/doc.go diff --git a/passkey/session/errors.go b/proof/passkey/session/errors.go similarity index 100% rename from passkey/session/errors.go rename to proof/passkey/session/errors.go diff --git a/passkey/session/memory.go b/proof/passkey/session/memory.go similarity index 100% rename from passkey/session/memory.go rename to proof/passkey/session/memory.go diff --git a/passkey/session/memory_test.go b/proof/passkey/session/memory_test.go similarity index 98% rename from passkey/session/memory_test.go rename to proof/passkey/session/memory_test.go index 0bc2779..ce0a7e6 100644 --- a/passkey/session/memory_test.go +++ b/proof/passkey/session/memory_test.go @@ -10,8 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/meigma/authkit/passkey" - "github.com/meigma/authkit/passkey/session" + "github.com/meigma/authkit/proof/passkey" + "github.com/meigma/authkit/proof/passkey/session" ) func TestMemoryStoreRegistrationRoundTrip(t *testing.T) { diff --git a/passkey/session/options.go b/proof/passkey/session/options.go similarity index 100% rename from passkey/session/options.go rename to proof/passkey/session/options.go diff --git a/passkey/session/types.go b/proof/passkey/session/types.go similarity index 97% rename from passkey/session/types.go rename to proof/passkey/session/types.go index 5f9518a..095e2c0 100644 --- a/passkey/session/types.go +++ b/proof/passkey/session/types.go @@ -5,7 +5,7 @@ import ( "github.com/go-webauthn/webauthn/webauthn" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" ) // Registration contains the server-side state needed to finish passkey registration. diff --git a/passkey/store.go b/proof/passkey/store.go similarity index 100% rename from passkey/store.go rename to proof/passkey/store.go diff --git a/passkey/types.go b/proof/passkey/types.go similarity index 100% rename from passkey/types.go rename to proof/passkey/types.go diff --git a/passkey/webauthn_user.go b/proof/passkey/webauthn_user.go similarity index 100% rename from passkey/webauthn_user.go rename to proof/passkey/webauthn_user.go diff --git a/roleauth/doc.go b/roleauth/doc.go deleted file mode 100644 index 0d48ca9..0000000 --- a/roleauth/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package roleauth authorizes requests from local role-derived action grants. -package roleauth diff --git a/store/memory/clone.go b/store/memory/clone.go index 4206604..932b89c 100644 --- a/store/memory/clone.go +++ b/store/memory/clone.go @@ -4,7 +4,7 @@ import ( "maps" "github.com/meigma/authkit" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) // cloneAttributes returns an independent copy of attrs. A nil or empty map diff --git a/store/memory/oidc.go b/store/memory/oidc.go index a4fd90a..35f573a 100644 --- a/store/memory/oidc.go +++ b/store/memory/oidc.go @@ -3,7 +3,7 @@ package memory import ( "context" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) // TrustProvider stores provider as trusted for its issuer. The provider is diff --git a/store/memory/oidc_test.go b/store/memory/oidc_test.go index ccc2787..c40730e 100644 --- a/store/memory/oidc_test.go +++ b/store/memory/oidc_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) func TestStoreSatisfiesOIDCContracts(t *testing.T) { diff --git a/store/memory/passkey.go b/store/memory/passkey.go index 89a3f65..7e5e74d 100644 --- a/store/memory/passkey.go +++ b/store/memory/passkey.go @@ -10,7 +10,7 @@ import ( "github.com/go-webauthn/webauthn/webauthn" "github.com/meigma/authkit" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" ) // FindUserByPrincipal returns the passkey user for principalID and rpID. diff --git a/store/memory/passkey_test.go b/store/memory/passkey_test.go index 776836e..90e077e 100644 --- a/store/memory/passkey_test.go +++ b/store/memory/passkey_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" ) func TestStoreSatisfiesPasskeyContracts(t *testing.T) { diff --git a/store/memory/store.go b/store/memory/store.go index 8c75d4f..d2c4987 100644 --- a/store/memory/store.go +++ b/store/memory/store.go @@ -4,9 +4,9 @@ import ( "sync" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" - "github.com/meigma/authkit/oidc" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/apikey" + "github.com/meigma/authkit/proof/oidc" + "github.com/meigma/authkit/proof/passkey" ) const principalIDPrefix = "principal_" diff --git a/store/memory/token.go b/store/memory/token.go index cf425ac..2db6c6e 100644 --- a/store/memory/token.go +++ b/store/memory/token.go @@ -7,7 +7,7 @@ import ( "time" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/proof/apikey" ) // CreateToken stores token. The token's PrincipalID must reference an diff --git a/store/memory/token_test.go b/store/memory/token_test.go index b67a589..4f7ad33 100644 --- a/store/memory/token_test.go +++ b/store/memory/token_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/proof/apikey" ) func TestStoreSatisfiesTokenContracts(t *testing.T) { diff --git a/store/postgres/clone.go b/store/postgres/clone.go index 9b7c5f3..8c4bd4c 100644 --- a/store/postgres/clone.go +++ b/store/postgres/clone.go @@ -4,7 +4,7 @@ import ( "maps" "github.com/meigma/authkit" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) // cloneAttributes returns an independent copy of attrs, or nil for an empty diff --git a/store/postgres/oidc.go b/store/postgres/oidc.go index ebe6f13..87e328f 100644 --- a/store/postgres/oidc.go +++ b/store/postgres/oidc.go @@ -7,7 +7,7 @@ import ( "github.com/jackc/pgx/v5" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) // TrustProvider stores provider as trusted for its issuer. The provider is diff --git a/store/postgres/oidc_test.go b/store/postgres/oidc_test.go index 9b6b715..f0ac590 100644 --- a/store/postgres/oidc_test.go +++ b/store/postgres/oidc_test.go @@ -3,7 +3,7 @@ package postgres import ( "testing" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) func TestStoreSatisfiesOIDCContracts(_ *testing.T) { diff --git a/store/postgres/passkey.go b/store/postgres/passkey.go index 55a0d61..4cf0378 100644 --- a/store/postgres/passkey.go +++ b/store/postgres/passkey.go @@ -11,7 +11,7 @@ import ( "github.com/jackc/pgx/v5" "github.com/meigma/authkit" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" ) // FindUserByPrincipal returns the passkey user for principalID and rpID, or diff --git a/store/postgres/passkey_test.go b/store/postgres/passkey_test.go index e02cadd..e4ec6b9 100644 --- a/store/postgres/passkey_test.go +++ b/store/postgres/passkey_test.go @@ -3,7 +3,7 @@ package postgres import ( "testing" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" ) func TestStoreSatisfiesPasskeyContracts(_ *testing.T) { diff --git a/store/postgres/token.go b/store/postgres/token.go index a2a48c2..22c3b1d 100644 --- a/store/postgres/token.go +++ b/store/postgres/token.go @@ -11,7 +11,7 @@ import ( "github.com/jackc/pgx/v5/pgtype" "github.com/meigma/authkit" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/proof/apikey" ) // CreateToken stores token. The token's PrincipalID must reference an diff --git a/store/postgres/token_test.go b/store/postgres/token_test.go index 5d3844f..132fd31 100644 --- a/store/postgres/token_test.go +++ b/store/postgres/token_test.go @@ -3,7 +3,7 @@ package postgres import ( "testing" - "github.com/meigma/authkit/apikey" + "github.com/meigma/authkit/proof/apikey" ) func TestStoreSatisfiesTokenContracts(_ *testing.T) { diff --git a/testkit/cmd/testkit/main_test.go b/testkit/cmd/testkit/main_test.go index 05aa410..8d47350 100644 --- a/testkit/cmd/testkit/main_test.go +++ b/testkit/cmd/testkit/main_test.go @@ -17,7 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" "github.com/meigma/authkit/testkit/internal/authflow" ) diff --git a/testkit/cmd/testkit/oidc_config.go b/testkit/cmd/testkit/oidc_config.go index efb1dff..609aec2 100644 --- a/testkit/cmd/testkit/oidc_config.go +++ b/testkit/cmd/testkit/oidc_config.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/meigma/authkit" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/proof/oidc" ) const ( diff --git a/testkit/cmd/testkit/passkey_config.go b/testkit/cmd/testkit/passkey_config.go index 706501c..5093090 100644 --- a/testkit/cmd/testkit/passkey_config.go +++ b/testkit/cmd/testkit/passkey_config.go @@ -5,7 +5,7 @@ import ( "net" "strings" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/proof/passkey" "github.com/meigma/authkit/testkit/internal/authflow" ) diff --git a/testkit/internal/authflow/runtime.go b/testkit/internal/authflow/runtime.go index 1b2dfd1..b60207f 100644 --- a/testkit/internal/authflow/runtime.go +++ b/testkit/internal/authflow/runtime.go @@ -14,13 +14,13 @@ import ( "github.com/lestrrat-go/jwx/v3/jwk" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" - "github.com/meigma/authkit/apikey" - "github.com/meigma/authkit/compose" + "github.com/meigma/authkit/access/jwt" "github.com/meigma/authkit/exchange" - "github.com/meigma/authkit/httpauth" - "github.com/meigma/authkit/oidc" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/http/auth" + "github.com/meigma/authkit/http/compose" + "github.com/meigma/authkit/proof/apikey" + "github.com/meigma/authkit/proof/oidc" + "github.com/meigma/authkit/proof/passkey" "github.com/meigma/authkit/provisioning" ) @@ -79,7 +79,7 @@ type Store interface { // Runtime contains the authkit components used by testkit HTTP handlers. type Runtime struct { // Middleware authenticates requests carrying authkit access JWTs. - Middleware *httpauth.Middleware + Middleware *auth.Middleware pipeline *authkit.Pipeline @@ -234,8 +234,8 @@ func NewRuntime(ctx context.Context, store Store, opts ...Option) (*Runtime, err compose.AccessJWT(accessVerifier, store), }, Authorizer: pasteAuthorizer{}, - MiddlewareOptions: []httpauth.Option{ - httpauth.WithErrorRenderer(renderAuthError), + MiddlewareOptions: []auth.Option{ + auth.WithErrorRenderer(renderAuthError), }, }) if err != nil { @@ -398,7 +398,7 @@ func (r *Runtime) AuthorizeAuthenticated( } // SetAccessCookie writes the temporary testkit access JWT cookie. -func SetAccessCookie(w http.ResponseWriter, token accessjwt.IssuedToken) { +func SetAccessCookie(w http.ResponseWriter, token jwt.IssuedToken) { http.SetCookie(w, &http.Cookie{ Name: CookieName, Value: token.Plaintext, @@ -527,7 +527,7 @@ func principalStringAttribute(principal authkit.Principal, name string) string { func newAccessJWTIssuerAndVerifier( clock func() time.Time, -) (*accessjwt.Issuer, *accessjwt.Verifier, error) { +) (*jwt.Issuer, *jwt.Verifier, error) { rawKey, err := rsa.GenerateKey(rand.Reader, rsaKeyBits) if err != nil { return nil, nil, fmt.Errorf("authflow: generate access JWT key: %w", err) @@ -551,7 +551,7 @@ func newAccessJWTIssuerAndVerifier( return nil, nil, fmt.Errorf("authflow: build access JWT key set: %w", addErr) } - issuer, err := accessjwt.NewIssuer(accessjwt.IssuerOptions{ + issuer, err := jwt.NewIssuer(jwt.IssuerOptions{ Issuer: accessJWTIssuer, Audience: accessJWTAudience, TTL: AccessTokenTTL, @@ -561,7 +561,7 @@ func newAccessJWTIssuerAndVerifier( if err != nil { return nil, nil, fmt.Errorf("authflow: create access JWT issuer: %w", err) } - verifier, err := accessjwt.NewVerifier(accessjwt.VerifierOptions{ + verifier, err := jwt.NewVerifier(jwt.VerifierOptions{ Issuer: accessJWTIssuer, Audience: accessJWTAudience, KeySet: keySet, diff --git a/testkit/internal/authflow/runtime_integration_test.go b/testkit/internal/authflow/runtime_integration_test.go index f7eff70..17eabae 100644 --- a/testkit/internal/authflow/runtime_integration_test.go +++ b/testkit/internal/authflow/runtime_integration_test.go @@ -17,8 +17,8 @@ import ( "github.com/testcontainers/testcontainers-go/wait" "github.com/meigma/authkit" - "github.com/meigma/authkit/httpauth" - "github.com/meigma/authkit/oidc" + "github.com/meigma/authkit/http/auth" + "github.com/meigma/authkit/proof/oidc" authpostgres "github.com/meigma/authkit/store/postgres" testkitpostgres "github.com/meigma/authkit/testkit/internal/store/postgres" ) @@ -41,7 +41,7 @@ func TestRuntimeUsesPostgresAuthStore(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/protected", nil) req.Header.Set("Authorization", bearer(result.AccessToken.Plaintext)) runtime.Authenticate(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - principal, ok := httpauth.PrincipalFromContext(req.Context()) + principal, ok := auth.PrincipalFromContext(req.Context()) assert.True(t, ok) if ok { assert.Equal(t, runtime.Principal.ID, principal.ID) @@ -88,7 +88,7 @@ func TestRuntimeUsesPostgresAuthStoreForOIDCExchange(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/protected", nil) req.Header.Set("Authorization", bearer(result.AccessToken.Plaintext)) runtime.Authenticate(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - principal, ok := httpauth.PrincipalFromContext(req.Context()) + principal, ok := auth.PrincipalFromContext(req.Context()) assert.True(t, ok) if ok { assert.Equal(t, result.Principal.ID, principal.ID) diff --git a/testkit/internal/authflow/runtime_test.go b/testkit/internal/authflow/runtime_test.go index bc2991d..f3e57a8 100644 --- a/testkit/internal/authflow/runtime_test.go +++ b/testkit/internal/authflow/runtime_test.go @@ -19,9 +19,9 @@ import ( "github.com/stretchr/testify/require" "github.com/meigma/authkit" - "github.com/meigma/authkit/httpauth" - "github.com/meigma/authkit/oidc" - "github.com/meigma/authkit/passkey" + "github.com/meigma/authkit/http/auth" + "github.com/meigma/authkit/proof/oidc" + "github.com/meigma/authkit/proof/passkey" "github.com/meigma/authkit/store/memory" ) @@ -39,7 +39,7 @@ func TestRuntimeExchangesSeedAPITokenForAccessJWT(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/protected", nil) req.Header.Set("Authorization", bearer(result.AccessToken.Plaintext)) runtime.Authenticate(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - principal, ok := httpauth.PrincipalFromContext(req.Context()) + principal, ok := auth.PrincipalFromContext(req.Context()) assert.True(t, ok) if ok { assert.Equal(t, runtime.Principal.ID, principal.ID) @@ -200,7 +200,7 @@ func TestRuntimeExchangesOIDCTokenForAccessJWT(t *testing.T) { req := httptest.NewRequest(http.MethodGet, "/protected", nil) req.Header.Set("Authorization", bearer(result.AccessToken.Plaintext)) runtime.Authenticate(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - principal, ok := httpauth.PrincipalFromContext(req.Context()) + principal, ok := auth.PrincipalFromContext(req.Context()) assert.True(t, ok) if ok { assert.Equal(t, result.Principal.ID, principal.ID) diff --git a/testkit/internal/httpui/handlers.go b/testkit/internal/httpui/handlers.go index 8ebd80e..eb2a384 100644 --- a/testkit/internal/httpui/handlers.go +++ b/testkit/internal/httpui/handlers.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/meigma/authkit" - "github.com/meigma/authkit/httpauth" + "github.com/meigma/authkit/http/auth" "github.com/meigma/authkit/testkit/internal/authflow" "github.com/meigma/authkit/testkit/internal/paste" ) @@ -354,7 +354,7 @@ func (s *Server) authenticationFromRequest( w http.ResponseWriter, req *http.Request, ) (authkit.Authentication, bool) { - authentication, ok := httpauth.AuthenticationFromContext(req.Context()) + authentication, ok := auth.AuthenticationFromContext(req.Context()) if !ok { s.renderError(w, http.StatusInternalServerError, "Authentication context is missing.") diff --git a/testkit/internal/httpui/passkey_handlers.go b/testkit/internal/httpui/passkey_handlers.go index e0a7282..bbad863 100644 --- a/testkit/internal/httpui/passkey_handlers.go +++ b/testkit/internal/httpui/passkey_handlers.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/meigma/authkit" - "github.com/meigma/authkit/passkey" - passkeysession "github.com/meigma/authkit/passkey/session" + "github.com/meigma/authkit/proof/passkey" + passkeysession "github.com/meigma/authkit/proof/passkey/session" "github.com/meigma/authkit/testkit/internal/authflow" ) diff --git a/testkit/internal/httpui/server.go b/testkit/internal/httpui/server.go index 580a4b0..608c13f 100644 --- a/testkit/internal/httpui/server.go +++ b/testkit/internal/httpui/server.go @@ -11,8 +11,8 @@ import ( "github.com/meigma/authkit" "github.com/meigma/authkit/exchange" - "github.com/meigma/authkit/passkey" - passkeysession "github.com/meigma/authkit/passkey/session" + "github.com/meigma/authkit/proof/passkey" + passkeysession "github.com/meigma/authkit/proof/passkey/session" "github.com/meigma/authkit/testkit/internal/authflow" "github.com/meigma/authkit/testkit/internal/paste" ) diff --git a/testkit/internal/httpui/server_test.go b/testkit/internal/httpui/server_test.go index 9f0582b..7bd1cb2 100644 --- a/testkit/internal/httpui/server_test.go +++ b/testkit/internal/httpui/server_test.go @@ -21,14 +21,14 @@ import ( "github.com/lestrrat-go/jwx/v3/jwa" "github.com/lestrrat-go/jwx/v3/jwk" - "github.com/lestrrat-go/jwx/v3/jwt" + jwxjwt "github.com/lestrrat-go/jwx/v3/jwt" "github.com/meigma/authkit" - "github.com/meigma/authkit/accessjwt" + "github.com/meigma/authkit/access/jwt" "github.com/meigma/authkit/exchange" - "github.com/meigma/authkit/oidc" - "github.com/meigma/authkit/passkey" - passkeysession "github.com/meigma/authkit/passkey/session" + "github.com/meigma/authkit/proof/oidc" + "github.com/meigma/authkit/proof/passkey" + passkeysession "github.com/meigma/authkit/proof/passkey/session" authmemory "github.com/meigma/authkit/store/memory" "github.com/meigma/authkit/testkit/internal/authflow" "github.com/meigma/authkit/testkit/internal/paste" @@ -245,7 +245,7 @@ func TestServerPasskeyLoginFinishSetsAccessCookie(t *testing.T) { auth := &fakeAuthRuntime{ finishPasskeyLoginResult: exchange.IdentityResult{ Principal: authkit.Principal{ID: "principal-1"}, - AccessToken: accessjwt.IssuedToken{ + AccessToken: jwt.IssuedToken{ Plaintext: "access-token", PrincipalID: "principal-1", ExpiresAt: fixedTime().Add(time.Hour), @@ -358,7 +358,7 @@ func TestServerRejectsPasskeyLoginFinishCeremonyFailures(t *testing.T) { t.Run(tt.name, func(t *testing.T) { auth := &fakeAuthRuntime{ finishPasskeyLoginResult: exchange.IdentityResult{ - AccessToken: accessjwt.IssuedToken{ + AccessToken: jwt.IssuedToken{ Plaintext: "access-token", PrincipalID: "principal-1", ExpiresAt: fixedTime().Add(time.Hour), @@ -1404,7 +1404,7 @@ func (i *testIssuer) provider() oidc.Provider { func (i *testIssuer) sign(t *testing.T, req oidcTokenRequest) string { t.Helper() - builder := jwt.NewBuilder(). + builder := jwxjwt.NewBuilder(). Issuer(i.issuer). Subject(req.subject). Audience(req.audiences). @@ -1416,7 +1416,7 @@ func (i *testIssuer) sign(t *testing.T, req oidcTokenRequest) string { token, err := builder.Build() require.NoError(t, err) - signed, err := jwt.Sign(token, jwt.WithKey(jwa.RS256(), i.signingKey)) + signed, err := jwxjwt.Sign(token, jwxjwt.WithKey(jwa.RS256(), i.signingKey)) require.NoError(t, err) return string(signed)