Skip to content

Commit 7d38890

Browse files
committed
Change OIDC init to lazy-load instead of loading once on boot. Fixes #2626.
1 parent 9611164 commit 7d38890

File tree

2 files changed

+95
-30
lines changed

2 files changed

+95
-30
lines changed

cmd/auth.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ type oidcState struct {
3434
Next string `json:"next"`
3535
}
3636

37-
var oidcProviders = map[string]bool{
38-
"google.com": true,
39-
"microsoftonline.com": true,
40-
"auth0.com": true,
41-
"github.com": true,
37+
var oidcProviders = map[string]struct{}{
38+
"google.com": {},
39+
"microsoftonline.com": {},
40+
"auth0.com": {},
41+
"github.com": {},
4242
}
4343

4444
// LoginPage renders the login page and handles the login form.

internal/auth/auth.go

Lines changed: 90 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -84,27 +84,6 @@ func New(cfg Config, db *sql.DB, cb *Callbacks, lo *log.Logger) (*Auth, error) {
8484
apiUsers: map[string]User{},
8585
}
8686

87-
// Initialize OIDC.
88-
if cfg.OIDC.Enabled {
89-
provider, err := oidc.NewProvider(context.Background(), cfg.OIDC.ProviderURL)
90-
if err != nil {
91-
cfg.OIDC.Enabled = false
92-
lo.Printf("error initializing OIDC OAuth provider: %v", err)
93-
} else {
94-
a.verifier = provider.Verifier(&oidc.Config{
95-
ClientID: cfg.OIDC.ClientID,
96-
})
97-
98-
a.oauthCfg = oauth2.Config{
99-
ClientID: cfg.OIDC.ClientID,
100-
ClientSecret: cfg.OIDC.ClientSecret,
101-
Endpoint: provider.Endpoint(),
102-
RedirectURL: cfg.OIDC.RedirectURL,
103-
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
104-
}
105-
a.provider = provider
106-
}
107-
}
10887

10988
// Initialize session manager.
11089
a.sess = simplesessions.New(simplesessions.Options{
@@ -167,15 +146,91 @@ func (o *Auth) GetAPIToken(user string, token string) (User, bool) {
167146
return t, true
168147
}
169148

149+
// initOIDC initializes the OIDC provider, verifier, and OAuth config.
150+
func (o *Auth) initOIDC() error {
151+
if !o.cfg.OIDC.Enabled {
152+
return fmt.Errorf("OIDC is not enabled")
153+
}
154+
155+
provider, err := oidc.NewProvider(context.Background(), o.cfg.OIDC.ProviderURL)
156+
if err != nil {
157+
return fmt.Errorf("error initializing OIDC OAuth provider: %v", err)
158+
}
159+
160+
o.verifier = provider.Verifier(&oidc.Config{
161+
ClientID: o.cfg.OIDC.ClientID,
162+
})
163+
164+
o.oauthCfg = oauth2.Config{
165+
ClientID: o.cfg.OIDC.ClientID,
166+
ClientSecret: o.cfg.OIDC.ClientSecret,
167+
Endpoint: provider.Endpoint(),
168+
RedirectURL: o.cfg.OIDC.RedirectURL,
169+
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
170+
}
171+
o.provider = provider
172+
173+
return nil
174+
}
175+
176+
// getProvider returns the OIDC provider, initializing it if necessary.
177+
func (o *Auth) getProvider() (*oidc.Provider, error) {
178+
o.Lock()
179+
defer o.Unlock()
180+
181+
if o.provider == nil {
182+
if err := o.initOIDC(); err != nil {
183+
return nil, err
184+
}
185+
}
186+
return o.provider, nil
187+
}
188+
189+
// getVerifier returns the OIDC verifier, initializing it if necessary.
190+
func (o *Auth) getVerifier() (*oidc.IDTokenVerifier, error) {
191+
o.Lock()
192+
defer o.Unlock()
193+
194+
if o.verifier == nil {
195+
if err := o.initOIDC(); err != nil {
196+
return nil, err
197+
}
198+
}
199+
return o.verifier, nil
200+
}
201+
202+
// getOAuthConfig returns the OAuth config, initializing it if necessary.
203+
func (o *Auth) getOAuthConfig() (*oauth2.Config, error) {
204+
o.Lock()
205+
defer o.Unlock()
206+
207+
if o.oauthCfg.ClientID == "" {
208+
if err := o.initOIDC(); err != nil {
209+
return nil, err
210+
}
211+
}
212+
return &o.oauthCfg, nil
213+
}
214+
170215
// GetOIDCAuthURL returns the OIDC provider's auth URL to redirect to.
171216
func (o *Auth) GetOIDCAuthURL(state, nonce string) string {
172-
return o.oauthCfg.AuthCodeURL(state, oidc.Nonce(nonce))
217+
cfg, err := o.getOAuthConfig()
218+
if err != nil {
219+
o.log.Printf("error getting OAuth config: %v", err)
220+
return ""
221+
}
222+
return cfg.AuthCodeURL(state, oidc.Nonce(nonce))
173223
}
174224

175225
// ExchangeOIDCToken takes an OIDC authorization code (recieved via redirect from the OIDC provider),
176226
// validates it, and returns an OIDC token for subsequent auth.
177227
func (o *Auth) ExchangeOIDCToken(code, nonce string) (string, OIDCclaim, error) {
178-
tk, err := o.oauthCfg.Exchange(context.TODO(), code)
228+
cfg, err := o.getOAuthConfig()
229+
if err != nil {
230+
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("error getting OAuth config: %v", err))
231+
}
232+
233+
tk, err := cfg.Exchange(context.TODO(), code)
179234
if err != nil {
180235
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("error exchanging token: %v", err))
181236
}
@@ -185,7 +240,12 @@ func (o *Auth) ExchangeOIDCToken(code, nonce string) (string, OIDCclaim, error)
185240
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, "`id_token` missing.")
186241
}
187242

188-
idTk, err := o.verifier.Verify(context.TODO(), rawIDTk)
243+
verifier, err := o.getVerifier()
244+
if err != nil {
245+
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("error getting verifier: %v", err))
246+
}
247+
248+
idTk, err := verifier.Verify(context.TODO(), rawIDTk)
189249
if err != nil {
190250
return "", OIDCclaim{}, echo.NewHTTPError(http.StatusUnauthorized, fmt.Sprintf("error verifying ID token: %v", err))
191251
}
@@ -201,7 +261,12 @@ func (o *Auth) ExchangeOIDCToken(code, nonce string) (string, OIDCclaim, error)
201261

202262
// If claims doesn't have the e-mail, attempt to fetch it from the userinfo endpoint.
203263
if claims.Email == "" {
204-
userInfo, err := o.provider.UserInfo(context.TODO(), oauth2.StaticTokenSource(tk))
264+
provider, err := o.getProvider()
265+
if err != nil {
266+
return "", OIDCclaim{}, fmt.Errorf("error getting provider: %v", err)
267+
}
268+
269+
userInfo, err := provider.UserInfo(context.TODO(), oauth2.StaticTokenSource(tk))
205270
if err != nil {
206271
return "", OIDCclaim{}, errors.New("error fetching user info from OIDC")
207272
}

0 commit comments

Comments
 (0)