refactor: use struct types for claim related types

BREAKING change.
The following types are changed from interface to struct type:

- AccessTokenClaims
- IDTokenClaims
- IntrospectionResponse
- UserInfo and related types.

The following methods of OPStorage now take a pointer to a struct type,
instead of an interface:

- SetUserinfoFromScopes
- SetUserinfoFromToken
- SetIntrospectionFromToken

The following functions are now generic, so that type-safe extension
of Claims is now possible:

- op.VerifyIDTokenHint
- op.VerifyAccessToken
- rp.VerifyTokens
- rp.VerifyIDToken
This commit is contained in:
Tim Möhlmann 2023-02-17 16:50:28 +02:00
parent 11682a2cc8
commit 85bd99873d
40 changed files with 857 additions and 1291 deletions

View file

@ -9,7 +9,6 @@ import (
"path"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"golang.org/x/text/language"
@ -22,8 +21,10 @@ const dataDir = "regression_data"
// dataDir/<type_name>.json
func jsonFilename(obj interface{}) string {
name := fmt.Sprintf("%T.json", obj)
name, _ = strings.CutPrefix(name, "*")
return path.Join(dataDir, name)
return path.Join(
dataDir,
strings.TrimPrefix(name, "*"),
)
}
func encodeJSON(t *testing.T, w io.Writer, obj interface{}) {
@ -33,70 +34,86 @@ func encodeJSON(t *testing.T, w io.Writer, obj interface{}) {
}
var (
accessTokenRegressData = &accessTokenClaims{
Issuer: "zitadel",
Subject: "hello@me.com",
Audience: Audience{"foo", "bar"},
Expiration: Time(time.Unix(12345, 0)),
IssuedAt: Time(time.Unix(12000, 0)),
NotBefore: Time(time.Unix(12000, 0)),
JWTID: "900",
AuthorizedParty: "just@me.com",
Nonce: "6969",
AuthTime: Time(time.Unix(12000, 0)),
CodeHash: "hashhash",
AuthenticationContextClassReference: "something",
AuthenticationMethodsReferences: []string{"some", "methods"},
SessionID: "666",
Scopes: []string{"email", "phone"},
ClientID: "777",
AccessTokenUseNumber: 22,
claims: map[string]interface{}{
accessTokenRegressData = &AccessTokenClaims{
RegisteredAccessTokenClaims: RegisteredAccessTokenClaims{
TokenClaims: TokenClaims{
Issuer: "zitadel",
Subject: "hello@me.com",
Audience: Audience{"foo", "bar"},
Expiration: 12345,
IssuedAt: 12000,
JWTID: "900",
AuthorizedParty: "just@me.com",
Nonce: "6969",
AuthTime: 12000,
AuthenticationContextClassReference: "something",
AuthenticationMethodsReferences: []string{"some", "methods"},
ClientID: "777",
SignatureAlg: jose.ES256,
},
NotBefore: 12000,
CodeHash: "hashhash",
SessionID: "666",
Scopes: []string{"email", "phone"},
AccessTokenUseNumber: 22,
},
Claims: map[string]interface{}{
"foo": "bar",
},
signatureAlg: jose.ES256,
}
idTokenRegressData = &idTokenClaims{
Issuer: "zitadel",
Audience: Audience{"foo", "bar"},
Expiration: Time(time.Unix(12345, 0)),
NotBefore: Time(time.Unix(12000, 0)),
IssuedAt: Time(time.Unix(12000, 0)),
JWTID: "900",
AuthorizedParty: "just@me.com",
Nonce: "6969",
AuthTime: Time(time.Unix(12000, 0)),
AccessTokenHash: "acthashhash",
CodeHash: "hashhash",
AuthenticationContextClassReference: "something",
AuthenticationMethodsReferences: []string{"some", "methods"},
ClientID: "777",
UserInfo: userInfoRegressData,
signatureAlg: jose.ES256,
idTokenRegressData = &IDTokenClaims{
RegisteredIDTokenClaims: RegisteredIDTokenClaims{
TokenClaims: TokenClaims{
Issuer: "zitadel",
Subject: "hello@me.com",
Audience: Audience{"foo", "bar"},
Expiration: 12345,
IssuedAt: 12000,
JWTID: "900",
AuthorizedParty: "just@me.com",
Nonce: "6969",
AuthTime: 12000,
AuthenticationContextClassReference: "something",
AuthenticationMethodsReferences: []string{"some", "methods"},
ClientID: "777",
SignatureAlg: jose.ES256,
},
NotBefore: 12000,
AccessTokenHash: "acthashhash",
CodeHash: "hashhash",
UserInfoProfile: userInfoRegressData.UserInfoProfile,
UserInfoEmail: userInfoRegressData.UserInfoEmail,
UserInfoPhone: userInfoRegressData.UserInfoPhone,
Address: userInfoRegressData.Address,
},
Claims: map[string]interface{}{
"foo": "bar",
},
}
introspectionResponseRegressData = &introspectionResponse{
introspectionResponseRegressData = &IntrospectionResponse{
Active: true,
Scope: SpaceDelimitedArray{"email", "phone"},
ClientID: "777",
TokenType: "idtoken",
Expiration: Time(time.Unix(12345, 0)),
IssuedAt: Time(time.Unix(12000, 0)),
NotBefore: Time(time.Unix(12000, 0)),
Expiration: 12345,
IssuedAt: 12000,
NotBefore: 12000,
Subject: "hello@me.com",
Audience: Audience{"foo", "bar"},
Issuer: "zitadel",
JWTID: "900",
userInfoProfile: userInfoRegressData.userInfoProfile,
userInfoEmail: userInfoRegressData.userInfoEmail,
userInfoPhone: userInfoRegressData.userInfoPhone,
Username: "muhlemmer",
UserInfoProfile: userInfoRegressData.UserInfoProfile,
UserInfoEmail: userInfoRegressData.UserInfoEmail,
UserInfoPhone: userInfoRegressData.UserInfoPhone,
Address: userInfoRegressData.Address,
claims: map[string]interface{}{
Claims: map[string]interface{}{
"foo": "bar",
},
}
userInfoRegressData = &userinfo{
userInfoRegressData = &UserInfo{
Subject: "hello@me.com",
userInfoProfile: userInfoProfile{
UserInfoProfile: UserInfoProfile{
Name: "Tim Möhlmann",
GivenName: "Tim",
FamilyName: "Möhlmann",
@ -108,19 +125,19 @@ var (
Gender: "male",
Birthdate: "1st of April",
Zoneinfo: "Europe/Amsterdam",
Locale: language.Dutch,
UpdatedAt: Time(time.Unix(1, 1)),
Locale: NewLocale(language.Dutch),
UpdatedAt: 1,
PreferredUsername: "muhlemmer",
},
userInfoEmail: userInfoEmail{
UserInfoEmail: UserInfoEmail{
Email: "tim@zitadel.com",
EmailVerified: true,
},
userInfoPhone: userInfoPhone{
UserInfoPhone: UserInfoPhone{
PhoneNumber: "+1234567890",
PhoneNumberVerified: true,
},
Address: &userInfoAddress{
Address: UserInfoAddress{
Formatted: "Sesame street 666\n666-666, Smallvile\nMoon",
StreetAddress: "Sesame street 666",
Locality: "Smallvile",
@ -128,7 +145,7 @@ var (
PostalCode: "666-666",
Country: "Moon",
},
claims: map[string]interface{}{
Claims: map[string]interface{}{
"foo": "bar",
},
}
@ -138,8 +155,8 @@ var (
Issuer: "zitadel",
Subject: "hello@me.com",
Audience: Audience{"foo", "bar"},
Expiration: Time(time.Unix(12345, 0)),
IssuedAt: Time(time.Unix(12000, 0)),
Expiration: 12345,
IssuedAt: 12000,
customClaims: map[string]interface{}{
"foo": "bar",
},