Files
upstream-ory-kratos/session/tokenizer_test.go
upstream-mirror c60cc7ca75
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
2026-09-15 21:19:12 +05:00

167 lines
5.7 KiB
Go

// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package session_test
import (
"context"
_ "embed"
"net/http/httptest"
"testing"
"time"
"github.com/gofrs/uuid"
"github.com/golang-jwt/jwt/v5"
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ory/herodot"
"github.com/ory/kratos/driver/config"
"github.com/ory/kratos/identity"
"github.com/ory/kratos/pkg"
"github.com/ory/kratos/pkg/testhelpers"
"github.com/ory/kratos/session"
"github.com/ory/x/configx"
"github.com/ory/x/contextx"
"github.com/ory/x/snapshotx"
)
//go:embed stub/jwk.es256.json
var es256Key []byte
//go:embed stub/jwk.es512.json
var es512Key []byte
func validateTokenized(t *testing.T, raw string, key []byte) *jwt.Token {
token, err := jwt.Parse(
raw,
func(token *jwt.Token) (target interface{}, _ error) {
set, err := jwk.Parse(key)
if err != nil {
return nil, err
}
key, _ := set.Key(0)
if pk, err := key.PublicKey(); err != nil {
return nil, err
} else if err := pk.Raw(&target); err != nil {
return nil, err
}
return target, nil
},
// We use a fixed time function for snapshot testing, and thus can not validate claims.
jwt.WithoutClaimsValidation(),
)
require.NoError(t, err)
return token
}
func setTokenizeConfig(ctx context.Context, templateID, keyFile, mapper string) context.Context {
return contextx.WithConfigValue(ctx, config.ViperKeySessionTokenizerTemplates+"."+templateID, &config.SessionTokenizeFormat{
TTL: time.Minute,
JWKSURL: "file://stub/" + keyFile,
ClaimsMapperURL: mapper,
})
}
func setTokenizeConfigWitSubjectSource(ctx context.Context, templateID, keyFile, mapper, subjectSource string) context.Context {
return contextx.WithConfigValue(ctx, config.ViperKeySessionTokenizerTemplates+"."+templateID, &config.SessionTokenizeFormat{
TTL: time.Minute,
JWKSURL: "file://stub/" + keyFile,
ClaimsMapperURL: mapper,
SubjectSource: subjectSource,
})
}
func TestTokenizer(t *testing.T) {
t.Parallel()
_, reg := pkg.NewFastRegistryWithMocks(t,
configx.WithValue(config.ViperKeyPublicBaseURL, "http://localhost/"),
configx.WithValues(testhelpers.DefaultIdentitySchemaConfig("file://./stub/identity.schema.json")),
)
tkn := session.NewTokenizer(reg)
nowDate := time.Date(2023, 02, 01, 00, 00, 00, 0, time.UTC)
tkn.SetNowFunc(func() time.Time {
return nowDate.Round(time.Second)
})
r := httptest.NewRequest("GET", "/sessions/whoami", nil)
i := identity.NewIdentity("default")
i.ID = uuid.FromStringOrNil("7458af86-c1d8-401c-978a-8da89133f78b")
i.ExternalID = "external-id"
i.NID = uuid.Must(uuid.NewV4())
s, err := testhelpers.NewActiveSession(r, reg, i, time.Now(), identity.CredentialsTypePassword, identity.AuthenticatorAssuranceLevel1)
require.NoError(t, err)
s.ID = uuid.FromStringOrNil("432caf86-c1d8-401c-978a-8da89133f78b")
iWithoutExtID := identity.NewIdentity("default")
iWithoutExtID.ID = uuid.FromStringOrNil("710678c5-7761-455a-9e3b-be66e3019da2")
iWithoutExtID.NID = i.NID
s2, err := testhelpers.NewActiveSession(r, reg, iWithoutExtID, time.Now(), identity.CredentialsTypePassword, identity.AuthenticatorAssuranceLevel1)
require.NoError(t, err)
s2.ID = uuid.FromStringOrNil("44de370d-c8ae-4e2c-b943-5e9d9cc385da")
t.Run("case=es256-without-jsonnet", func(t *testing.T) {
tid := "es256-no-template"
ctx := setTokenizeConfig(t.Context(), tid, "jwk.es256.json", "")
require.NoError(t, tkn.TokenizeSession(ctx, tid, s))
token := validateTokenized(t, s.Tokenized, es256Key)
resultClaims := token.Claims.(jwt.MapClaims)
assert.Equal(t, i.ID.String(), resultClaims["sub"])
assert.Equal(t, s.ID.String(), resultClaims["sid"])
assert.NotEmpty(t, resultClaims["jti"])
assert.EqualValues(t, resultClaims["exp"], nowDate.Add(time.Minute).Unix())
snapshotx.SnapshotT(t, token.Claims, snapshotx.ExceptPaths("jti"))
})
t.Run("case=es512-without-jsonnet", func(t *testing.T) {
tid := "es512-no-template"
ctx := setTokenizeConfig(t.Context(), tid, "jwk.es512.json", "")
require.NoError(t, tkn.TokenizeSession(ctx, tid, s))
token := validateTokenized(t, s.Tokenized, es512Key)
snapshotx.SnapshotT(t, token.Claims, snapshotx.ExceptPaths("jti"))
})
t.Run("case=rs512-with-jsonnet", func(t *testing.T) {
tid := "rs512-template"
ctx := setTokenizeConfigWitSubjectSource(t.Context(), tid, "jwk.es512.json", "file://stub/rs512-template.jsonnet", "id")
require.NoError(t, tkn.TokenizeSession(ctx, tid, s))
token := validateTokenized(t, s.Tokenized, es512Key)
snapshotx.SnapshotT(t, token.Claims, snapshotx.ExceptPaths("jti"))
})
t.Run("case=rs512-with-external_id-in-sub", func(t *testing.T) {
tid := "rs512-template"
ctx := setTokenizeConfigWitSubjectSource(t.Context(), tid, "jwk.es512.json", "file://stub/rs512-template.jsonnet", "external_id")
require.NoError(t, tkn.TokenizeSession(ctx, tid, s))
token := validateTokenized(t, s.Tokenized, es512Key)
snapshotx.SnapshotT(t, token.Claims, snapshotx.ExceptPaths("jti"))
})
t.Run("case=rs512-with-empty-external_id-in-sub", func(t *testing.T) {
tid := "rs512-template"
ctx := setTokenizeConfigWitSubjectSource(t.Context(), tid, "jwk.es512.json", "file://stub/rs512-template.jsonnet", "external_id")
// This should fail because the identity does not have an external ID set.
require.Error(t, tkn.TokenizeSession(ctx, tid, s2))
})
t.Run("case=rs512-with-broken-keyfile", func(t *testing.T) {
tid := "rs512-template"
ctx := setTokenizeConfig(t.Context(), tid, "jwk.es512.broken.json", "file://stub/rs512-template.jsonnet")
err := tkn.TokenizeSession(ctx, tid, s)
require.ErrorIs(t, err, herodot.ErrBadRequest())
})
}