diff --git a/auth/access-token.go b/auth/access-token.go index 7b54e4d..17e8ab7 100644 --- a/auth/access-token.go +++ b/auth/access-token.go @@ -25,3 +25,13 @@ func CreateAccessToken(p mjwt.Signer, sub, id string, aud jwt.ClaimStrings, perm func CreateAccessTokenWithDuration(p mjwt.Signer, dur time.Duration, sub, id string, aud jwt.ClaimStrings, perms *claims.PermStorage) (string, error) { return p.GenerateJwt(sub, id, aud, dur, &AccessTokenClaims{Perms: perms}) } + +// CreateAccessTokenWithKID creates an access token with the default 15 minute duration and the specified kID +func CreateAccessTokenWithKID(p mjwt.Signer, sub, id string, aud jwt.ClaimStrings, perms *claims.PermStorage, kID string) (string, error) { + return CreateAccessTokenWithDurationAndKID(p, time.Minute*15, sub, id, aud, perms, kID) +} + +// CreateAccessTokenWithDurationAndKID creates an access token with a custom duration and the specified kID +func CreateAccessTokenWithDurationAndKID(p mjwt.Signer, dur time.Duration, sub, id string, aud jwt.ClaimStrings, perms *claims.PermStorage, kID string) (string, error) { + return p.GenerateJwtWithKID(sub, id, aud, dur, &AccessTokenClaims{Perms: perms}, kID) +} diff --git a/auth/pair.go b/auth/pair.go index b2ce969..7d50e55 100644 --- a/auth/pair.go +++ b/auth/pair.go @@ -26,3 +26,23 @@ func CreateTokenPairWithDuration(p mjwt.Signer, accessDur, refreshDur time.Durat } return accessToken, refreshToken, nil } + +// CreateTokenPairWithKID creates an access and refresh token pair using the default +// 15 minute and 7 day durations respectively using the specified kID +func CreateTokenPairWithKID(p mjwt.Signer, sub, id, rId string, aud, rAud jwt.ClaimStrings, perms *claims.PermStorage, kID string) (string, string, error) { + return CreateTokenPairWithDurationAndKID(p, time.Minute*15, time.Hour*24*7, sub, id, rId, aud, rAud, perms, kID) +} + +// CreateTokenPairWithDurationAndKID creates an access and refresh token pair using +// custom durations for the access and refresh tokens +func CreateTokenPairWithDurationAndKID(p mjwt.Signer, accessDur, refreshDur time.Duration, sub, id, rId string, aud, rAud jwt.ClaimStrings, perms *claims.PermStorage, kID string) (string, string, error) { + accessToken, err := CreateAccessTokenWithDurationAndKID(p, accessDur, sub, id, aud, perms, kID) + if err != nil { + return "", "", err + } + refreshToken, err := CreateRefreshTokenWithDurationAndKID(p, refreshDur, sub, rId, id, rAud, kID) + if err != nil { + return "", "", err + } + return accessToken, refreshToken, nil +} diff --git a/auth/refresh-token.go b/auth/refresh-token.go index 5667885..b0b4675 100644 --- a/auth/refresh-token.go +++ b/auth/refresh-token.go @@ -24,3 +24,13 @@ func CreateRefreshToken(p mjwt.Signer, sub, id, ati string, aud jwt.ClaimStrings func CreateRefreshTokenWithDuration(p mjwt.Signer, dur time.Duration, sub, id, ati string, aud jwt.ClaimStrings) (string, error) { return p.GenerateJwt(sub, id, aud, dur, RefreshTokenClaims{AccessTokenId: ati}) } + +// CreateRefreshTokenWithKID creates a refresh token with the default 7 day duration and the specified kID +func CreateRefreshTokenWithKID(p mjwt.Signer, sub, id, ati string, aud jwt.ClaimStrings, kID string) (string, error) { + return CreateRefreshTokenWithDurationAndKID(p, time.Hour*24*7, sub, id, ati, aud, kID) +} + +// CreateRefreshTokenWithDurationAndKID creates a refresh token with a custom duration and the specified kID +func CreateRefreshTokenWithDurationAndKID(p mjwt.Signer, dur time.Duration, sub, id, ati string, aud jwt.ClaimStrings, kID string) (string, error) { + return p.GenerateJwtWithKID(sub, id, aud, dur, RefreshTokenClaims{AccessTokenId: ati}, kID) +} diff --git a/cmd/mjwt/access.go b/cmd/mjwt/access.go index d4c2330..113d3e7 100644 --- a/cmd/mjwt/access.go +++ b/cmd/mjwt/access.go @@ -16,7 +16,7 @@ import ( ) type accessCmd struct { - issuer, subject, id, audience, duration string + issuer, subject, id, audience, duration, kID string } func (s *accessCmd) Name() string { return "access" } @@ -24,7 +24,7 @@ func (s *accessCmd) Synopsis() string { return "Generates an access token with permissions using the private key" } func (s *accessCmd) Usage() string { - return `sign [-iss ] [-sub ] [-id ] [-aud ] [-dur ] + return `sign [-iss ] [-sub ] [-id ] [-aud ] [-dur ] [-kid ] Output a signed MJWT token with the specified permissions. ` } @@ -35,6 +35,7 @@ func (s *accessCmd) SetFlags(f *flag.FlagSet) { f.StringVar(&s.id, "id", "", "MJWT ID") f.StringVar(&s.audience, "aud", "", "Comma separated audience items for the MJWT") f.StringVar(&s.duration, "dur", "15m", "Duration for the MJWT (default: 15m)") + f.StringVar(&s.kID, "kid", "\x00", "The Key ID of the signing key") } func (s *accessCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { @@ -65,8 +66,17 @@ func (s *accessCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{} return subcommands.ExitFailure } - signer := mjwt.NewMJwtSigner(s.issuer, key) - token, err := signer.GenerateJwt(s.subject, s.id, aud, dur, auth.AccessTokenClaims{Perms: ps}) + var token string + if len(s.kID) == 1 && s.kID[0] == '\x00' { + signer := mjwt.NewMJwtSigner(s.issuer, key) + token, err = signer.GenerateJwt(s.subject, s.id, aud, dur, auth.AccessTokenClaims{Perms: ps}) + } else { + kStore := mjwt.NewMJwtKeyStore() + kStore.SetKey(s.kID, key) + signer := mjwt.NewMJwtSignerWithKeyStore(s.issuer, nil, kStore) + token, err = signer.GenerateJwtWithKID(s.subject, s.id, aud, dur, auth.AccessTokenClaims{Perms: ps}, s.kID) + } + if err != nil { _, _ = fmt.Fprintln(os.Stderr, "Error: Failed to generate MJWT token: ", err) return subcommands.ExitFailure