|
|
|
@ -352,9 +352,9 @@ 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,omitempty"`
|
|
|
|
|
IDToken string `json:"id_token"`
|
|
|
|
|
// KeyAuth ({challenge-token}.{jwk-thumbprint})
|
|
|
|
|
KeyAuth string `json:"keyauth,omitempty"`
|
|
|
|
|
KeyAuth string `json:"keyauth"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func wireOIDC01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, payload []byte) error {
|
|
|
|
@ -448,7 +448,7 @@ func wireOIDC01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSO
|
|
|
|
|
|
|
|
|
|
type wireDpopPayload struct {
|
|
|
|
|
// AccessToken is the token generated by wire-server
|
|
|
|
|
AccessToken string `json:"access_token,omitempty"`
|
|
|
|
|
AccessToken string `json:"access_token"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func wireDPOP01Validate(ctx context.Context, ch *Challenge, db DB, accountJWK *jose.JSONWebKey, payload []byte) error {
|
|
|
|
@ -484,13 +484,14 @@ func wireDPOP01Validate(ctx context.Context, ch *Challenge, db DB, accountJWK *j
|
|
|
|
|
return WrapErrorISE(err, "invalid Go template registered for 'target'")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
params := verifyParams{
|
|
|
|
|
params := wireVerifyParams{
|
|
|
|
|
token: dpopPayload.AccessToken,
|
|
|
|
|
tokenKey: dpopOptions.GetSigningKey(),
|
|
|
|
|
dpopKey: accountJWK,
|
|
|
|
|
dpopKey: accountJWK.Public(),
|
|
|
|
|
dpopKeyID: accountJWK.KeyID,
|
|
|
|
|
issuer: issuer,
|
|
|
|
|
wireID: wireID,
|
|
|
|
|
challenge: ch,
|
|
|
|
|
chToken: ch.Token,
|
|
|
|
|
t: clock.Now().UTC(),
|
|
|
|
|
}
|
|
|
|
|
_, dpop, err := parseAndVerifyWireAccessToken(params)
|
|
|
|
@ -523,33 +524,34 @@ func wireDPOP01Validate(ctx context.Context, ch *Challenge, db DB, accountJWK *j
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type cnf struct {
|
|
|
|
|
Kid string `json:"kid,omitempty"`
|
|
|
|
|
type wireCnf struct {
|
|
|
|
|
Kid string `json:"kid"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type wireAccessToken struct {
|
|
|
|
|
jose.Claims
|
|
|
|
|
Challenge string `json:"chal,omitempty"`
|
|
|
|
|
Cnf *cnf `json:"cnf,omitempty"`
|
|
|
|
|
Proof string `json:"proof,omitempty"`
|
|
|
|
|
ClientID string `json:"client_id,omitempty"`
|
|
|
|
|
APIVersion int `json:"api_version,omitempty"`
|
|
|
|
|
Scope string `json:"scope,omitempty"`
|
|
|
|
|
Challenge string `json:"chal"`
|
|
|
|
|
Cnf wireCnf `json:"cnf"`
|
|
|
|
|
Proof string `json:"proof"`
|
|
|
|
|
ClientID string `json:"client_id"`
|
|
|
|
|
APIVersion int `json:"api_version"`
|
|
|
|
|
Scope string `json:"scope"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type wireDpopToken map[string]any
|
|
|
|
|
|
|
|
|
|
type verifyParams struct {
|
|
|
|
|
type wireVerifyParams struct {
|
|
|
|
|
token string
|
|
|
|
|
tokenKey crypto.PublicKey
|
|
|
|
|
dpopKey *jose.JSONWebKey
|
|
|
|
|
dpopKey crypto.PublicKey
|
|
|
|
|
dpopKeyID string
|
|
|
|
|
issuer string
|
|
|
|
|
wireID wire.ID
|
|
|
|
|
challenge *Challenge
|
|
|
|
|
chToken string
|
|
|
|
|
t time.Time
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func parseAndVerifyWireAccessToken(v verifyParams) (*wireAccessToken, *wireDpopToken, error) {
|
|
|
|
|
func parseAndVerifyWireAccessToken(v wireVerifyParams) (*wireAccessToken, *wireDpopToken, error) {
|
|
|
|
|
jwt, err := jose.ParseSigned(v.token)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, fmt.Errorf("failed parsing token: %w", err)
|
|
|
|
@ -567,17 +569,8 @@ func parseAndVerifyWireAccessToken(v verifyParams) (*wireAccessToken, *wireDpopT
|
|
|
|
|
return nil, nil, fmt.Errorf("failed validation: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rawKid, err := v.dpopKey.Thumbprint(crypto.SHA256)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, nil, fmt.Errorf("failed to compute JWK thumbprint")
|
|
|
|
|
}
|
|
|
|
|
kid := base64.RawURLEncoding.EncodeToString(rawKid)
|
|
|
|
|
|
|
|
|
|
if accessToken.Cnf == nil {
|
|
|
|
|
return nil, nil, errors.New("'cnf' is nil")
|
|
|
|
|
}
|
|
|
|
|
if accessToken.Cnf.Kid != kid {
|
|
|
|
|
return nil, nil, fmt.Errorf("expected kid %q; got %q", kid, accessToken.Cnf.Kid)
|
|
|
|
|
if accessToken.Cnf.Kid != v.dpopKeyID {
|
|
|
|
|
return nil, nil, fmt.Errorf("expected kid %q; got %q", v.dpopKeyID, accessToken.Cnf.Kid)
|
|
|
|
|
}
|
|
|
|
|
if accessToken.ClientID != v.wireID.ClientID {
|
|
|
|
|
return nil, nil, fmt.Errorf("invalid Wire client ID %q", accessToken.ClientID)
|
|
|
|
@ -591,7 +584,7 @@ func parseAndVerifyWireAccessToken(v verifyParams) (*wireAccessToken, *wireDpopT
|
|
|
|
|
return nil, nil, fmt.Errorf("invalid Wire DPoP token: %w", err)
|
|
|
|
|
}
|
|
|
|
|
var dpopToken wireDpopToken
|
|
|
|
|
if err := dpopJWT.Claims(v.dpopKey.Key, &dpopToken); err != nil {
|
|
|
|
|
if err := dpopJWT.Claims(v.dpopKey, &dpopToken); err != nil {
|
|
|
|
|
return nil, nil, fmt.Errorf("failed validating Wire DPoP token claims: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -599,7 +592,7 @@ func parseAndVerifyWireAccessToken(v verifyParams) (*wireAccessToken, *wireDpopT
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil, nil, fmt.Errorf("invalid challenge in Wire DPoP token")
|
|
|
|
|
}
|
|
|
|
|
if challenge != v.challenge.Token {
|
|
|
|
|
if challenge != v.chToken {
|
|
|
|
|
return nil, nil, fmt.Errorf("invalid Wire DPoP challenge %q", challenge)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|