Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3b6a39f

Browse files
committed
fix: always attempt external auth refresh when fetching
1 parentecae6f9 commit3b6a39f

File tree

1 file changed

+84
-70
lines changed

1 file changed

+84
-70
lines changed

‎coderd/workspaceagents.go

Lines changed: 84 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,78 +2031,25 @@ func (api *API) workspaceAgentsExternalAuth(rw http.ResponseWriter, r *http.Requ
20312031
return
20322032
}
20332033

2034-
iflisten {
2035-
// Since we're ticking frequently and this sign-in operation is rare,
2036-
// we are OK with polling to avoid the complexity of pubsub.
2037-
ticker,done:=api.NewTicker(time.Second)
2038-
deferdone()
2039-
varpreviousToken database.ExternalAuthLink
2040-
for {
2041-
select {
2042-
case<-ctx.Done():
2043-
return
2044-
case<-ticker:
2045-
}
2046-
externalAuthLink,err:=api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{
2047-
ProviderID:externalAuthConfig.ID,
2048-
UserID:workspace.OwnerID,
2049-
})
2050-
iferr!=nil {
2051-
iferrors.Is(err,sql.ErrNoRows) {
2052-
continue
2053-
}
2054-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2055-
Message:"Failed to get external auth link.",
2056-
Detail:err.Error(),
2057-
})
2058-
return
2059-
}
2060-
2061-
// Expiry may be unset if the application doesn't configure tokens
2062-
// to expire.
2063-
// See
2064-
// https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app.
2065-
ifexternalAuthLink.OAuthExpiry.Before(dbtime.Now())&&!externalAuthLink.OAuthExpiry.IsZero() {
2066-
continue
2067-
}
2068-
2069-
// Only attempt to revalidate an oauth token if it has actually changed.
2070-
// No point in trying to validate the same token over and over again.
2071-
ifpreviousToken.OAuthAccessToken==externalAuthLink.OAuthAccessToken&&
2072-
previousToken.OAuthRefreshToken==externalAuthLink.OAuthRefreshToken&&
2073-
previousToken.OAuthExpiry==externalAuthLink.OAuthExpiry {
2074-
continue
2075-
}
2076-
2077-
valid,_,err:=externalAuthConfig.ValidateToken(ctx,externalAuthLink.OAuthAccessToken)
2078-
iferr!=nil {
2079-
api.Logger.Warn(ctx,"failed to validate external auth token",
2080-
slog.F("workspace_owner_id",workspace.OwnerID.String()),
2081-
slog.F("validate_url",externalAuthConfig.ValidateURL),
2082-
slog.Error(err),
2083-
)
2084-
}
2085-
previousToken=externalAuthLink
2086-
if!valid {
2087-
continue
2088-
}
2089-
resp,err:=createExternalAuthResponse(externalAuthConfig.Type,externalAuthLink.OAuthAccessToken,externalAuthLink.OAuthExtra)
2090-
iferr!=nil {
2091-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2092-
Message:"Failed to create external auth response.",
2093-
Detail:err.Error(),
2094-
})
2095-
return
2096-
}
2097-
httpapi.Write(ctx,rw,http.StatusOK,resp)
2034+
// handleRetrying will attempt to continually check for a new token
2035+
// if listen is true. This is useful if an error is encountered in the
2036+
// original single flow.
2037+
//
2038+
// By default, if no errors are encountered, then the single flow response
2039+
// is returned.
2040+
handleRetrying:=func(codeint,responseany) {
2041+
if!listen {
2042+
httpapi.Write(ctx,rw,code,response)
20982043
return
20992044
}
2045+
2046+
api.workspaceAgentsExternalAuthListen(rw,ctx,externalAuthConfig,workspace)
21002047
}
21012048

21022049
// This is the URL that will redirect the user with a state token.
21032050
redirectURL,err:=api.AccessURL.Parse(fmt.Sprintf("/external-auth/%s",externalAuthConfig.ID))
21042051
iferr!=nil {
2105-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2052+
handleRetrying(http.StatusInternalServerError, codersdk.Response{
21062053
Message:"Failed to parse access URL.",
21072054
Detail:err.Error(),
21082055
})
@@ -2115,36 +2062,36 @@ func (api *API) workspaceAgentsExternalAuth(rw http.ResponseWriter, r *http.Requ
21152062
})
21162063
iferr!=nil {
21172064
if!errors.Is(err,sql.ErrNoRows) {
2118-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2065+
handleRetrying(http.StatusInternalServerError, codersdk.Response{
21192066
Message:"Failed to get external auth link.",
21202067
Detail:err.Error(),
21212068
})
21222069
return
21232070
}
21242071

2125-
httpapi.Write(ctx,rw,http.StatusOK, agentsdk.ExternalAuthResponse{
2072+
handleRetrying(http.StatusOK, agentsdk.ExternalAuthResponse{
21262073
URL:redirectURL.String(),
21272074
})
21282075
return
21292076
}
21302077

21312078
externalAuthLink,updated,err:=externalAuthConfig.RefreshToken(ctx,api.Database,externalAuthLink)
21322079
iferr!=nil {
2133-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2080+
handleRetrying(http.StatusInternalServerError, codersdk.Response{
21342081
Message:"Failed to refresh external auth token.",
21352082
Detail:err.Error(),
21362083
})
21372084
return
21382085
}
21392086
if!updated {
2140-
httpapi.Write(ctx,rw,http.StatusOK, agentsdk.ExternalAuthResponse{
2087+
handleRetrying(http.StatusOK, agentsdk.ExternalAuthResponse{
21412088
URL:redirectURL.String(),
21422089
})
21432090
return
21442091
}
21452092
resp,err:=createExternalAuthResponse(externalAuthConfig.Type,externalAuthLink.OAuthAccessToken,externalAuthLink.OAuthExtra)
21462093
iferr!=nil {
2147-
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2094+
handleRetrying(http.StatusInternalServerError, codersdk.Response{
21482095
Message:"Failed to create external auth response.",
21492096
Detail:err.Error(),
21502097
})
@@ -2153,6 +2100,73 @@ func (api *API) workspaceAgentsExternalAuth(rw http.ResponseWriter, r *http.Requ
21532100
httpapi.Write(ctx,rw,http.StatusOK,resp)
21542101
}
21552102

2103+
func (api*API)workspaceAgentsExternalAuthListen(rw http.ResponseWriter,ctx context.Context,externalAuthConfig*externalauth.Config,workspace database.Workspace) {
2104+
// Since we're ticking frequently and this sign-in operation is rare,
2105+
// we are OK with polling to avoid the complexity of pubsub.
2106+
ticker,done:=api.NewTicker(time.Second)
2107+
deferdone()
2108+
varpreviousToken database.ExternalAuthLink
2109+
for {
2110+
select {
2111+
case<-ctx.Done():
2112+
return
2113+
case<-ticker:
2114+
}
2115+
externalAuthLink,err:=api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{
2116+
ProviderID:externalAuthConfig.ID,
2117+
UserID:workspace.OwnerID,
2118+
})
2119+
iferr!=nil {
2120+
iferrors.Is(err,sql.ErrNoRows) {
2121+
continue
2122+
}
2123+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2124+
Message:"Failed to get external auth link.",
2125+
Detail:err.Error(),
2126+
})
2127+
return
2128+
}
2129+
2130+
// Expiry may be unset if the application doesn't configure tokens
2131+
// to expire.
2132+
// See
2133+
// https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app.
2134+
ifexternalAuthLink.OAuthExpiry.Before(dbtime.Now())&&!externalAuthLink.OAuthExpiry.IsZero() {
2135+
continue
2136+
}
2137+
2138+
// Only attempt to revalidate an oauth token if it has actually changed.
2139+
// No point in trying to validate the same token over and over again.
2140+
ifpreviousToken.OAuthAccessToken==externalAuthLink.OAuthAccessToken&&
2141+
previousToken.OAuthRefreshToken==externalAuthLink.OAuthRefreshToken&&
2142+
previousToken.OAuthExpiry==externalAuthLink.OAuthExpiry {
2143+
continue
2144+
}
2145+
2146+
valid,_,err:=externalAuthConfig.ValidateToken(ctx,externalAuthLink.OAuthAccessToken)
2147+
iferr!=nil {
2148+
api.Logger.Warn(ctx,"failed to validate external auth token",
2149+
slog.F("workspace_owner_id",workspace.OwnerID.String()),
2150+
slog.F("validate_url",externalAuthConfig.ValidateURL),
2151+
slog.Error(err),
2152+
)
2153+
}
2154+
previousToken=externalAuthLink
2155+
if!valid {
2156+
continue
2157+
}
2158+
resp,err:=createExternalAuthResponse(externalAuthConfig.Type,externalAuthLink.OAuthAccessToken,externalAuthLink.OAuthExtra)
2159+
iferr!=nil {
2160+
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
2161+
Message:"Failed to create external auth response.",
2162+
Detail:err.Error(),
2163+
})
2164+
return
2165+
}
2166+
httpapi.Write(ctx,rw,http.StatusOK,resp)
2167+
}
2168+
}
2169+
21562170
// createExternalAuthResponse creates an ExternalAuthResponse based on the
21572171
// provider type. This is to support legacy `/workspaceagents/me/gitauth`
21582172
// which uses `Username` and `Password`.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp