From 1c8ee5cb88fa3722e738383476de3da88c2076c4 Mon Sep 17 00:00:00 2001 From: yyefimov Date: Wed, 15 Oct 2025 13:37:37 -0400 Subject: [PATCH] fix(coderd): support string type for oidc response's expires_in json property (#20152) Some versions of Azure AD return expires_in property as string. Use json.Number to accept either integer or string and then convert to int64. Helpful links: https://learn.microsoft.com/en-us/answers/questions/2337020/azure-ad-token-endpoint-returns-expires-in-as-stri https://feedback.azure.com/d365community/idea/7772fd95-26e6-ec11-a81b-0022484ee92d --- coderd/oauthpki/oidcpki.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/coderd/oauthpki/oidcpki.go b/coderd/oauthpki/oidcpki.go index fa1c3854af..76f8d59c88 100644 --- a/coderd/oauthpki/oidcpki.go +++ b/coderd/oauthpki/oidcpki.go @@ -222,8 +222,9 @@ func (src *jwtTokenSource) Token() (*oauth2.Token, error) { RefreshToken string `json:"refresh_token,omitempty"` // Extra fields returned by the refresh that are needed - IDToken string `json:"id_token"` - ExpiresIn int64 `json:"expires_in"` // relative seconds from now + IDToken string `json:"id_token"` + ExpiresIn json.Number `json:"expires_in"` // relative seconds from now, use Number since Azure AD might return string + // error fields // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 ErrorCode string `json:"error"` @@ -256,8 +257,13 @@ func (src *jwtTokenSource) Token() (*oauth2.Token, error) { RefreshToken: tokenRes.RefreshToken, } - if secs := tokenRes.ExpiresIn; secs > 0 { - newToken.Expiry = time.Now().Add(time.Duration(secs) * time.Second) + expiresIn, convertErr := tokenRes.ExpiresIn.Int64() + if convertErr != nil { + return nil, xerrors.Errorf("oauth2: cannot convert expires_in to int64: %w", convertErr) + } + + if expiresIn > 0 { + newToken.Expiry = time.Now().Add(time.Duration(expiresIn) * time.Second) } // ID token is a JWT token. We can decode it to get the expiry.