Use key authorization from ID token and `handle` -> `preferred_username`

pull/1681/head
Herman Slatman 4 months ago
parent 36e14de882
commit 2f3819aa4e
No known key found for this signature in database
GPG Key ID: F4D8A44EA0A75A4F

@ -1729,11 +1729,11 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
TokenURL: "",
JWKSURL: "",
UserInfoURL: "",
Algorithms: []string{},
Algorithms: []string{"ES256"},
},
Config: &wire.Config{
ClientID: "integration test",
SignatureAlgorithms: []string{},
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: true,
SkipExpiryCheck: true,
SkipIssuerCheck: true,

@ -85,7 +85,7 @@ func TestWireIntegration(t *testing.T) {
"organization": "WireTest",
"commonName": {{ toJson .Oidc.name }}
},
"uris": [{{ toJson .Oidc.handle }}, {{ toJson .Dpop.sub }}],
"uris": [{{ toJson .Oidc.preferred_username }}, {{ toJson .Dpop.sub }}],
"keyUsage": ["digitalSignature"],
"extKeyUsage": ["clientAuth"]
}`,
@ -98,11 +98,11 @@ func TestWireIntegration(t *testing.T) {
TokenURL: "",
JWKSURL: "",
UserInfoURL: "",
Algorithms: []string{},
Algorithms: []string{"ES256"},
},
Config: &wire.Config{
ClientID: "integration test",
SignatureAlgorithms: []string{},
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: true,
SkipExpiryCheck: true,
SkipIssuerCheck: true,
@ -306,12 +306,16 @@ func TestWireIntegration(t *testing.T) {
jose.Claims
Challenge string `json:"chal,omitempty"`
Handle string `json:"handle,omitempty"`
Nonce string `json:"nonce,omitempty"`
HTU string `json:"htu,omitempty"`
}{
Claims: jose.Claims{
Subject: "wireapp://lJGYPz0ZRq2kvc_XpdaDlA!ed416ce8ecdd9fad@example.com",
},
Challenge: "token",
Handle: "wireapp://%40alice.smith.qa@example.com",
Nonce: "nonce",
HTU: "http://issuer.example.com",
})
require.NoError(t, err)
dpop, err := dpopSigner.Sign(dpopBytes)
@ -366,6 +370,7 @@ func TestWireIntegration(t *testing.T) {
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: "https://issuer.example.com",
@ -374,6 +379,7 @@ func TestWireIntegration(t *testing.T) {
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := oidcTokenSigner.Sign(tokenBytes)
@ -382,10 +388,8 @@ func TestWireIntegration(t *testing.T) {
require.NoError(t, err)
p, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
payload = p
@ -436,7 +440,7 @@ func TestWireIntegration(t *testing.T) {
t.Log("updated challenge:", challenge.ID, challenge.Status)
switch challenge.Type {
case acme.WIREOIDC01:
err = db.CreateOidcToken(ctx, order.ID, map[string]any{"name": "Smith, Alice M (QA)", "handle": "wireapp://%40alice.smith.qa@example.com"})
err = db.CreateOidcToken(ctx, order.ID, map[string]any{"name": "Smith, Alice M (QA)", "preferred_username": "wireapp://%40alice.smith.qa@example.com"})
require.NoError(t, err)
case acme.WIREDPOP01:
err = db.CreateDpopToken(ctx, order.ID, map[string]any{"sub": "wireapp://lJGYPz0ZRq2kvc_XpdaDlA!ed416ce8ecdd9fad@example.com"})

@ -355,8 +355,6 @@ func dns01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebK
type wireOidcPayload struct {
// IDToken contains the OIDC identity token
IDToken string `json:"id_token"`
// KeyAuth ({challenge-token}.{jwk-thumbprint})
KeyAuth string `json:"keyauth"`
}
func wireOIDC01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, payload []byte) error {
@ -381,16 +379,6 @@ func wireOIDC01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSO
return WrapErrorISE(err, "failed getting Wire options")
}
// TODO(hs): move this into validation below?
expectedKeyAuth, err := KeyAuthorization(ch.Token, jwk)
if err != nil {
return WrapErrorISE(err, "error determining key authorization")
}
if expectedKeyAuth != oidcPayload.KeyAuth {
return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"keyAuthorization does not match; expected %q, but got %q", expectedKeyAuth, oidcPayload.KeyAuth))
}
oidcOptions := wireOptions.GetOIDCOptions()
verifier := oidcOptions.GetProvider(ctx).Verifier(oidcOptions.GetConfig())
idToken, err := verifier.Verify(ctx, oidcPayload.IDToken)
@ -404,13 +392,23 @@ func wireOIDC01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSO
Handle string `json:"name"`
Issuer string `json:"iss,omitempty"`
GivenName string `json:"given_name,omitempty"`
KeyAuth string `json:"keyauth"` // TODO(hs): use this property instead of the one in the payload after https://github.com/wireapp/rusty-jwt-tools/tree/fix/keyauth is done
KeyAuth string `json:"keyauth"`
}
if err := idToken.Claims(&claims); err != nil {
return storeError(ctx, db, ch, true, WrapError(ErrorRejectedIdentifierType, err,
"error retrieving claims from ID token"))
}
// TODO(hs): move this into validation below?
expectedKeyAuth, err := KeyAuthorization(ch.Token, jwk)
if err != nil {
return WrapErrorISE(err, "error determining key authorization")
}
if expectedKeyAuth != claims.KeyAuth {
return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"keyAuthorization does not match; expected %q, but got %q", expectedKeyAuth, claims.KeyAuth))
}
transformedIDToken, err := validateWireOIDCClaims(oidcOptions, idToken, wireID)
if err != nil {
return storeError(ctx, db, ch, true, WrapError(ErrorRejectedIdentifierType, err, "claims in OIDC ID token don't match"))
@ -459,12 +457,12 @@ func validateWireOIDCClaims(o *wireprovisioner.OIDCOptions, token *oidc.IDToken,
return nil, fmt.Errorf("invalid 'name' %q after transformation", name)
}
handle, ok := transformed["handle"]
preferredUsername, ok := transformed["preferred_username"]
if !ok {
return nil, fmt.Errorf("transformed OIDC ID token does not contain 'handle'")
return nil, fmt.Errorf("transformed OIDC ID token does not contain 'preferred_username'")
}
if wireID.Handle != handle {
return nil, fmt.Errorf("invalid 'handle' %q after transformation", handle)
if wireID.Handle != preferredUsername {
return nil, fmt.Errorf("invalid 'preferred_username' %q after transformation", preferredUsername)
}
return transformed, nil

@ -891,6 +891,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -899,6 +900,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -907,10 +909,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -929,17 +929,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -978,7 +975,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
MockCreateOidcToken: func(ctx context.Context, orderID string, idToken map[string]interface{}) error {
assert.Equal(t, "orderID", orderID)
assert.Equal(t, "Alice Smith", idToken["name"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", idToken["handle"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", idToken["preferred_username"].(string))
return nil
},
},
@ -1079,16 +1076,13 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuerexample.com",
IssuerURL: "http://issuerexample.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},

@ -163,7 +163,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuer.example.com",
IssuerURL: "http://issuer.example.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
@ -322,7 +323,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuer.example.com",
IssuerURL: "http://issuer.example.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
@ -463,16 +465,13 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuer.example.com",
IssuerURL: "http://issuer.example.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -612,16 +611,13 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuer.example.com",
IssuerURL: "http://issuer.example.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -761,16 +757,13 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuer.example.com",
IssuerURL: "http://issuer.example.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -917,16 +910,13 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuer.example.com",
IssuerURL: "http://issuer.example.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1106,12 +1096,38 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
"fail/keyauth-mismatch": func(t *testing.T) test {
jwk, _ := mustAccountAndKeyAuthorization(t, "token")
signerJWK, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
require.NoError(t, err)
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.SignatureAlgorithm(signerJWK.Algorithm),
Key: signerJWK,
}, new(jose.SignerOptions))
require.NoError(t, err)
srv := mustJWKServer(t, signerJWK.Public())
tokenBytes, err := json.Marshal(struct {
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
Audience: []string{"test"},
Expiry: jose.NewNumericDate(time.Now().Add(1 * time.Minute)),
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40bob@wire.com",
KeyAuth: "wrong-keyauth",
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
require.NoError(t, err)
idToken, err := signed.CompactSerialize()
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: "some-token",
KeyAuth: "wrong-key-authorization",
IDToken: idToken,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1130,7 +1146,9 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://issuer.example.com",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
@ -1154,6 +1172,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Status: StatusPending,
Value: string(valueBytes),
},
srv: srv,
payload: payload,
ctx: ctx,
jwk: jwk,
@ -1170,7 +1189,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
assert.Equal(t, "urn:ietf:params:acme:error:rejectedIdentifier", k.Type)
assert.Equal(t, "The server will not issue certificates for the identifier", k.Detail)
assert.Equal(t, 400, k.Status)
assert.Contains(t, k.Err.Error(), `keyAuthorization does not match; expected`)
assert.Contains(t, k.Err.Error(), "keyAuthorization does not match")
}
}
return nil
@ -1194,6 +1213,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -1201,7 +1221,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Expiry: jose.NewNumericDate(time.Now().Add(1 * time.Minute)),
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
PreferredUsername: "wireapp://%40bob@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -1210,10 +1231,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1232,17 +1251,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1300,6 +1316,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -1308,6 +1325,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40bob@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -1316,10 +1334,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1338,17 +1354,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1384,7 +1397,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
assert.Equal(t, "urn:ietf:params:acme:error:rejectedIdentifier", k.Type)
assert.Equal(t, "The server will not issue certificates for the identifier", k.Detail)
assert.Equal(t, 400, k.Status)
assert.Equal(t, `claims in OIDC ID token don't match: invalid 'handle' "wireapp://%40bob@wire.com" after transformation`, k.Err.Error())
assert.Equal(t, `claims in OIDC ID token don't match: invalid 'preferred_username' "wireapp://%40bob@wire.com" after transformation`, k.Err.Error())
}
}
return nil
@ -1406,6 +1419,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -1414,6 +1428,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -1422,10 +1437,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1444,17 +1457,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1509,6 +1519,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -1517,6 +1528,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -1525,10 +1537,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1547,17 +1557,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1616,6 +1623,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -1624,6 +1632,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -1632,10 +1641,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1654,17 +1661,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1723,6 +1727,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -1731,6 +1736,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -1739,10 +1745,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1761,17 +1765,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1810,7 +1811,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
MockCreateOidcToken: func(ctx context.Context, orderID string, idToken map[string]interface{}) error {
assert.Equal(t, "orderID", orderID)
assert.Equal(t, "Alice Smith", idToken["name"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", idToken["handle"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", idToken["preferred_username"].(string))
return errors.New("fail")
},
},
@ -1836,6 +1837,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
jose.Claims
Name string `json:"name,omitempty"`
PreferredUsername string `json:"preferred_username,omitempty"`
KeyAuth string `json:"keyauth"`
}{
Claims: jose.Claims{
Issuer: srv.URL,
@ -1844,6 +1846,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
},
Name: "Alice Smith",
PreferredUsername: "wireapp://%40alice_wire@wire.com",
KeyAuth: keyAuth,
})
require.NoError(t, err)
signed, err := signer.Sign(tokenBytes)
@ -1852,10 +1855,8 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
require.NoError(t, err)
payload, err := json.Marshal(struct {
IDToken string `json:"id_token"`
KeyAuth string `json:"keyauth"`
}{
IDToken: idToken,
KeyAuth: keyAuth,
})
require.NoError(t, err)
valueBytes, err := json.Marshal(struct {
@ -1874,17 +1875,14 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
Wire: &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
IssuerURL: srv.URL,
JWKSURL: srv.URL + "/keys",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
SkipClientIDCheck: false,
SkipExpiryCheck: false,
SkipIssuerCheck: false,
InsecureSkipSignatureCheck: false,
Now: time.Now,
ClientID: "test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: "",
},
@ -1923,7 +1921,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
MockCreateOidcToken: func(ctx context.Context, orderID string, idToken map[string]interface{}) error {
assert.Equal(t, "orderID", orderID)
assert.Equal(t, "Alice Smith", idToken["name"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", idToken["handle"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", idToken["preferred_username"].(string))
return nil
},
},
@ -2034,16 +2032,18 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
opts := &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "http://dex:15818/dex",
IssuerURL: "http://dex:15818/dex",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "wireapp",
ClientID: "wireapp",
SignatureAlgorithms: []string{"ES256"},
Now: func() time.Time {
return time.Date(2024, 1, 12, 18, 32, 41, 0, time.UTC) // (Token Expiry: 2024-01-12 21:32:42 +0100 CET)
},
InsecureSkipSignatureCheck: true,
InsecureSkipSignatureCheck: true, // skipping signature check for this specific test
},
TransformTemplate: `{"name": "{{ .preferred_username }}", "handle": "{{ .name }}"}`,
TransformTemplate: `{"name": "{{ .preferred_username }}", "preferred_username": "{{ .name }}"}`,
},
DPOP: &wireprovisioner.DPOPOptions{
SigningKey: []byte(fakeKey),
@ -2069,7 +2069,7 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
got, err := validateWireOIDCClaims(o, idToken, wireID)
assert.NoError(t, err)
assert.Equal(t, "wireapp://%40alice_wire@wire.com", got["handle"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", got["preferred_username"].(string))
assert.Equal(t, "Alice Smith", got["name"].(string))
assert.Equal(t, "http://dex:15818/dex", got["iss"].(string))
}
@ -2083,11 +2083,13 @@ MCowBQYDK2VwAyEA5c+4NKZSNQcR1T8qN6SjwgdPZQ0Ge12Ylx/YeGAJ35k=
opts := &wireprovisioner.Options{
OIDC: &wireprovisioner.OIDCOptions{
Provider: &wireprovisioner.Provider{
IssuerURL: "https://issuer.example.com",
IssuerURL: "https://issuer.example.com",
Algorithms: []string{"ES256"},
},
Config: &wireprovisioner.Config{
ClientID: "unit test",
Now: time.Now,
ClientID: "unit test",
SignatureAlgorithms: []string{"ES256"},
Now: time.Now,
},
TransformTemplate: transformTemplate,
},
@ -2130,18 +2132,18 @@ func Test_idTokenTransformation(t *testing.T) {
require.NoError(t, err)
// default transformation sets preferred username to handle; name as name
assert.Equal(t, "Alice Smith", result["handle"].(string))
assert.Equal(t, "Alice Smith", result["preferred_username"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", result["name"].(string))
assert.Equal(t, "http://dex:15818/dex", result["iss"].(string))
// swap the preferred_name and the name
swap := `{"name": "{{ .preferred_username }}", "handle": "{{ .name }}"}`
swap := `{"name": "{{ .preferred_username }}", "preferred_username": "{{ .name }}"}`
opts = createWireOptions(t, swap)
result, err = opts.GetOIDCOptions().Transform(m)
require.NoError(t, err)
// with the transformation, handle now contains wireapp://%40alice_wire@wire.com, name contains Alice Smith
assert.Equal(t, "wireapp://%40alice_wire@wire.com", result["handle"].(string))
assert.Equal(t, "wireapp://%40alice_wire@wire.com", result["preferred_username"].(string))
assert.Equal(t, "Alice Smith", result["name"].(string))
assert.Equal(t, "http://dex:15818/dex", result["iss"].(string))
}

@ -270,7 +270,7 @@ func TestDB_GetOidcToken(t *testing.T) {
require.NoError(t, err)
token := dbOidcToken{
ID: "orderID",
Content: []byte(`{"name": "Alice Smith", "handle": "@alice.smith"}`),
Content: []byte(`{"name": "Alice Smith", "preferred_username": "@alice.smith"}`),
CreatedAt: time.Now(),
}
b, err := json.Marshal(token)
@ -283,8 +283,8 @@ func TestDB_GetOidcToken(t *testing.T) {
},
orderID: "orderID",
expected: map[string]any{
"name": "Alice Smith",
"handle": "@alice.smith",
"name": "Alice Smith",
"preferred_username": "@alice.smith",
},
}
},
@ -335,8 +335,8 @@ func TestDB_CreateOidcToken(t *testing.T) {
},
orderID: "orderID",
oidc: map[string]any{
"name": "Alice Smith",
"handle": "@alice.smith",
"name": "Alice Smith",
"preferred_username": "@alice.smith",
},
expectedErr: errors.New("failed saving oidc token: error saving acme oidc: fail"),
}
@ -351,8 +351,8 @@ func TestDB_CreateOidcToken(t *testing.T) {
},
orderID: "orderID",
oidc: map[string]any{
"name": "Alice Smith",
"handle": "@alice.smith",
"name": "Alice Smith",
"preferred_username": "@alice.smith",
},
}
},

@ -68,7 +68,7 @@ func (o *OIDCOptions) GetConfig() *oidc.Config {
}
}
const defaultTemplate = `{"name": "{{ .name }}", "handle": "{{ .preferred_username }}"}`
const defaultTemplate = `{"name": "{{ .name }}", "preferred_username": "{{ .preferred_username }}"}`
func (o *OIDCOptions) validateAndInitialize() (err error) {
if o.Provider == nil {

@ -11,9 +11,9 @@ import (
func TestOIDCOptions_Transform(t *testing.T) {
defaultTransform, err := parseTransform(``)
require.NoError(t, err)
swapTransform, err := parseTransform(`{"name": "{{ .preferred_username }}", "handle": "{{ .name }}"}`)
swapTransform, err := parseTransform(`{"name": "{{ .preferred_username }}", "preferred_username": "{{ .name }}"}`)
require.NoError(t, err)
funcTransform, err := parseTransform(`{"name": "{{ .name }}", "handle": "{{ first .usernames }}"}`)
funcTransform, err := parseTransform(`{"name": "{{ .name }}", "preferred_username": "{{ first .usernames }}"}`)
require.NoError(t, err)
type fields struct {
transform *template.Template
@ -67,7 +67,6 @@ func TestOIDCOptions_Transform(t *testing.T) {
},
want: map[string]any{
"name": "Example",
"handle": "Preferred",
"preferred_username": "Preferred",
},
},
@ -84,8 +83,7 @@ func TestOIDCOptions_Transform(t *testing.T) {
},
want: map[string]any{
"name": "Preferred",
"handle": "Example",
"preferred_username": "Preferred",
"preferred_username": "Example",
},
},
{
@ -100,9 +98,9 @@ func TestOIDCOptions_Transform(t *testing.T) {
},
},
want: map[string]any{
"name": "Example",
"handle": "name-1",
"usernames": []string{"name-1", "name-2", "name-3"},
"name": "Example",
"preferred_username": "name-1",
"usernames": []string{"name-1", "name-2", "name-3"},
},
},
}

Loading…
Cancel
Save