-
Notifications
You must be signed in to change notification settings - Fork 441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove rusty-jwt-cli
#1670
Remove rusty-jwt-cli
#1670
Conversation
…actor Wire ACME extension configuration refactor
Add OIDC token template transformation
Time: v.t, | ||
Issuer: v.issuer, | ||
}, 360*time.Second); err != nil { | ||
return nil, nil, fmt.Errorf("failed validation: %w", err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The access token must have a "nonce" claims that must just be present (without checking its value)
Time: v.t, | ||
Issuer: v.issuer, | ||
}, 360*time.Second); err != nil { | ||
return nil, nil, fmt.Errorf("failed validation: %w", err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The access token must have a "scope" claim equal to "wire_client_id"
Time: v.t, | ||
Issuer: v.issuer, | ||
}, 360*time.Second); err != nil { | ||
return nil, nil, fmt.Errorf("failed validation: %w", err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:Likewise an access token has a JWK in its header that must match the provided verifying key (v.tokenKey)
return nil, nil, fmt.Errorf("invalid Wire DPoP token: %w", err) | ||
} | ||
var dpopToken wireDpopToken | ||
if err := dpopJWT.Claims(v.dpopKey, &dpopToken); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DPoP token has a JWK in its header that must (its JWK thumbprint) be verified against the account kid (v.dpopKeyID)
return nil, nil, fmt.Errorf("invalid Wire DPoP token: %w", err) | ||
} | ||
var dpopToken wireDpopToken | ||
if err := dpopJWT.Claims(v.dpopKey, &dpopToken); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DPoP token must also be validated (ValidateWithLeeway) with max expiry and the same leeway
} | ||
|
||
return nil | ||
handle, ok := dpopToken["handle"].(string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DPoP token must have the same ClientId (v.wireID.ClientID) as the access token
return nil, nil, fmt.Errorf("invalid challenge in Wire DPoP token") | ||
} | ||
if challenge != v.chToken { | ||
return nil, nil, fmt.Errorf("invalid Wire DPoP challenge %q", challenge) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DPoP token must have the same "nonce" as the access token
return nil, nil, fmt.Errorf("invalid challenge in Wire DPoP token") | ||
} | ||
if challenge != v.chToken { | ||
return nil, nil, fmt.Errorf("invalid Wire DPoP challenge %q", challenge) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DPoP token must have the same issuer as the access token
SkipClientIDCheck bool `json:"-"` | ||
SkipExpiryCheck bool `json:"-"` | ||
SkipIssuerCheck bool `json:"-"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are these for? If you cannot configure them, are they something we want to keep?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like they are only used for testing purposes. We can add a comment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for InsecureSkipSignatureCheck
. And Now
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree you can remove them all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't removed them yet, as they're used in some tests. The OIDC discovery work might also affect these.
|
||
type Config struct { | ||
ClientID string `json:"clientId,omitempty"` | ||
SignatureAlgorithms []string `json:"signatureAlgorithms,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary anymore. It's also a property that is usually in the JWKs and on the id_token_signing_alg_values_supported
property of the openid-configuration. And you have those in the provider.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That leaves us with only the ClientID. Assuming the rest of fields are for testing, having something like this makes more sense to me:
type OIDCOptions struct {
ClientID string `json:"clientId,omitempty"` // omitempty?
Provider *Provider `json:"provider,omitempty"`
TransformTemplate string `json:"transform,omitempty"`
}
} | ||
|
||
func (o *Options) Validate() error { | ||
o.validateOnce.Do( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See previous comment. Check if changing the provisioner using the admin API or HUP will reset the full provisioner and, consequently, this once, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed this for now. I think it would work as expected with the ReloadAdminResources
doing a new Init
for every provisioner and replacing the provisioners, but I didn't want to block on this right now. Also, I think it should actually be part of the Init
(or just after that), instead of it being triggered inside of the actual handler, so let's do it the right way (later), instead of doing it now
Improve access and dpop token validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, but I still don't like how the OIDCOptions work. See my notes.
var claims struct { | ||
Name string `json:"preferred_username,omitempty"` | ||
Handle string `json:"name"` | ||
Issuer string `json:"iss,omitempty"` | ||
GivenName string `json:"given_name,omitempty"` | ||
KeyAuth string `json:"keyauth"` | ||
ACMEAudience string `json:"acme_aud,omitempty"` | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
omitempty
only makes sense for marshaling, and it looks like we're only unmarshaling here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will have a look at those. There's some more places I can remove them; tests primarily
|
||
type Config struct { | ||
ClientID string `json:"clientId,omitempty"` | ||
SignatureAlgorithms []string `json:"signatureAlgorithms,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some notes about the go-oidc
implementation:
- If signature algorithms are not set, then the algorithms used in the provider are used. The use case for it is to either restrict or set the algorithms if the provider doesn't have them.
- The client id is matched with a
string.Contains
to the token audience. - As it is, the
go-oidc
provider will download the JWKs on each request. The provider has a mechanism to cache and re-download the keys if the keyId does not match, they don't use any cache header, this will be ok in most cases, the exception would be if the implementation uses Key IDs that are not fingerprints. It would make more sense to cache the*oidc.Provider
rather than the provider config.
No description provided.