mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: implement disabling oidc issuer checks (#13991)
* use DANGEROUS prefix and drop a warning log
This commit is contained in:
@ -97,6 +97,9 @@ type FakeIDP struct {
|
||||
deviceCode *syncmap.Map[string, deviceFlow]
|
||||
|
||||
// hooks
|
||||
// hookWellKnown allows mutating the returned .well-known/configuration JSON.
|
||||
// Using this can break the IDP configuration, so be careful.
|
||||
hookWellKnown func(r *http.Request, j *ProviderJSON) error
|
||||
// hookValidRedirectURL can be used to reject a redirect url from the
|
||||
// IDP -> Application. Almost all IDPs have the concept of
|
||||
// "Authorized Redirect URLs". This can be used to emulate that.
|
||||
@ -151,6 +154,12 @@ func WithMiddlewares(mws ...func(http.Handler) http.Handler) func(*FakeIDP) {
|
||||
}
|
||||
}
|
||||
|
||||
func WithHookWellKnown(hook func(r *http.Request, j *ProviderJSON) error) func(*FakeIDP) {
|
||||
return func(f *FakeIDP) {
|
||||
f.hookWellKnown = hook
|
||||
}
|
||||
}
|
||||
|
||||
// WithRefresh is called when a refresh token is used. The email is
|
||||
// the email of the user that is being refreshed assuming the claims are correct.
|
||||
func WithRefresh(hook func(email string) error) func(*FakeIDP) {
|
||||
@ -753,7 +762,16 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler {
|
||||
mux.Get("/.well-known/openid-configuration", func(rw http.ResponseWriter, r *http.Request) {
|
||||
f.logger.Info(r.Context(), "http OIDC config", slogRequestFields(r)...)
|
||||
|
||||
_ = json.NewEncoder(rw).Encode(f.provider)
|
||||
cpy := f.provider
|
||||
if f.hookWellKnown != nil {
|
||||
err := f.hookWellKnown(r, &cpy)
|
||||
if err != nil {
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(rw).Encode(cpy)
|
||||
})
|
||||
|
||||
// Authorize is called when the user is redirected to the IDP to login.
|
||||
@ -1371,8 +1389,11 @@ func (f *FakeIDP) AppCredentials() (clientID string, clientSecret string) {
|
||||
return f.clientID, f.clientSecret
|
||||
}
|
||||
|
||||
// OIDCConfig returns the OIDC config to use for Coderd.
|
||||
func (f *FakeIDP) OIDCConfig(t testing.TB, scopes []string, opts ...func(cfg *coderd.OIDCConfig)) *coderd.OIDCConfig {
|
||||
func (f *FakeIDP) PublicKey() crypto.PublicKey {
|
||||
return f.key.Public()
|
||||
}
|
||||
|
||||
func (f *FakeIDP) OauthConfig(t testing.TB, scopes []string) *oauth2.Config {
|
||||
t.Helper()
|
||||
|
||||
if len(scopes) == 0 {
|
||||
@ -1391,22 +1412,50 @@ func (f *FakeIDP) OIDCConfig(t testing.TB, scopes []string, opts ...func(cfg *co
|
||||
RedirectURL: "https://redirect.com",
|
||||
Scopes: scopes,
|
||||
}
|
||||
f.cfg = oauthCfg
|
||||
|
||||
ctx := oidc.ClientContext(context.Background(), f.HTTPClient(nil))
|
||||
return oauthCfg
|
||||
}
|
||||
|
||||
func (f *FakeIDP) OIDCConfigSkipIssuerChecks(t testing.TB, scopes []string, opts ...func(cfg *coderd.OIDCConfig)) *coderd.OIDCConfig {
|
||||
ctx := oidc.InsecureIssuerURLContext(context.Background(), f.issuer)
|
||||
|
||||
return f.internalOIDCConfig(ctx, t, scopes, func(config *oidc.Config) {
|
||||
config.SkipIssuerCheck = true
|
||||
}, opts...)
|
||||
}
|
||||
|
||||
func (f *FakeIDP) OIDCConfig(t testing.TB, scopes []string, opts ...func(cfg *coderd.OIDCConfig)) *coderd.OIDCConfig {
|
||||
return f.internalOIDCConfig(context.Background(), t, scopes, nil, opts...)
|
||||
}
|
||||
|
||||
// OIDCConfig returns the OIDC config to use for Coderd.
|
||||
func (f *FakeIDP) internalOIDCConfig(ctx context.Context, t testing.TB, scopes []string, verifierOpt func(config *oidc.Config), opts ...func(cfg *coderd.OIDCConfig)) *coderd.OIDCConfig {
|
||||
t.Helper()
|
||||
|
||||
oauthCfg := f.OauthConfig(t, scopes)
|
||||
|
||||
ctx = oidc.ClientContext(ctx, f.HTTPClient(nil))
|
||||
p, err := oidc.NewProvider(ctx, f.provider.Issuer)
|
||||
require.NoError(t, err, "failed to create OIDC provider")
|
||||
|
||||
verifierConfig := &oidc.Config{
|
||||
ClientID: oauthCfg.ClientID,
|
||||
SupportedSigningAlgs: []string{
|
||||
"RS256",
|
||||
},
|
||||
// Todo: add support for Now()
|
||||
}
|
||||
if verifierOpt != nil {
|
||||
verifierOpt(verifierConfig)
|
||||
}
|
||||
|
||||
cfg := &coderd.OIDCConfig{
|
||||
OAuth2Config: oauthCfg,
|
||||
Provider: p,
|
||||
Verifier: oidc.NewVerifier(f.provider.Issuer, &oidc.StaticKeySet{
|
||||
PublicKeys: []crypto.PublicKey{f.key.Public()},
|
||||
}, &oidc.Config{
|
||||
ClientID: oauthCfg.ClientID,
|
||||
SupportedSigningAlgs: []string{
|
||||
"RS256",
|
||||
},
|
||||
// Todo: add support for Now()
|
||||
}),
|
||||
}, verifierConfig),
|
||||
UsernameField: "preferred_username",
|
||||
EmailField: "email",
|
||||
AuthURLParams: map[string]string{"access_type": "offline"},
|
||||
@ -1419,13 +1468,12 @@ func (f *FakeIDP) OIDCConfig(t testing.TB, scopes []string, opts ...func(cfg *co
|
||||
opt(cfg)
|
||||
}
|
||||
|
||||
f.cfg = oauthCfg
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (f *FakeIDP) getClaims(m *syncmap.Map[string, jwt.MapClaims], key string) (jwt.MapClaims, bool) {
|
||||
v, ok := m.Load(key)
|
||||
if !ok {
|
||||
if !ok || v == nil {
|
||||
if f.defaultIDClaims != nil {
|
||||
return f.defaultIDClaims, true
|
||||
}
|
||||
|
Reference in New Issue
Block a user