@@ -41,7 +41,6 @@ import (
41
41
"github.com/coder/coder/v2/coderd/userpassword"
42
42
"github.com/coder/coder/v2/codersdk"
43
43
"github.com/coder/coder/v2/cryptorand"
44
- "github.com/coder/coder/v2/site"
45
44
)
46
45
47
46
const (
@@ -665,7 +664,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
665
664
})
666
665
cookies , user , key , err := api .oauthLogin (r , params )
667
666
defer params .CommitAuditLogs ()
668
- var httpErr httpError
667
+ var httpErr idpsync. HttpError
669
668
if xerrors .As (err , & httpErr ) {
670
669
httpErr .Write (rw , r )
671
670
return
@@ -1065,7 +1064,7 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
1065
1064
})
1066
1065
cookies , user , key , err := api .oauthLogin (r , params )
1067
1066
defer params .CommitAuditLogs ()
1068
- var httpErr httpError
1067
+ var httpErr idpsync. HttpError
1069
1068
if xerrors .As (err , & httpErr ) {
1070
1069
httpErr .Write (rw , r )
1071
1070
return
@@ -1093,7 +1092,7 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
1093
1092
}
1094
1093
1095
1094
// oidcGroups returns the groups for the user from the OIDC claims.
1096
- func (api * API ) oidcGroups (ctx context.Context , mergedClaims map [string ]interface {}) (bool , []string , * httpError ) {
1095
+ func (api * API ) oidcGroups (ctx context.Context , mergedClaims map [string ]interface {}) (bool , []string , * idpsync. HttpError ) {
1097
1096
logger := api .Logger .Named (userAuthLoggerName )
1098
1097
usingGroups := false
1099
1098
var groups []string
@@ -1114,11 +1113,11 @@ func (api *API) oidcGroups(ctx context.Context, mergedClaims map[string]interfac
1114
1113
slog .F ("type" , fmt .Sprintf ("%T" , groupsRaw )),
1115
1114
slog .Error (err ),
1116
1115
)
1117
- return false , nil , & httpError {
1118
- code : http .StatusBadRequest ,
1119
- msg : "Failed to sync groups from OIDC claims" ,
1120
- detail : err .Error (),
1121
- renderStaticPage : false ,
1116
+ return false , nil , & idpsync. HttpError {
1117
+ Code : http .StatusBadRequest ,
1118
+ Msg : "Failed to sync groups from OIDC claims" ,
1119
+ Detail : err .Error (),
1120
+ RenderStaticPage : false ,
1122
1121
}
1123
1122
}
1124
1123
@@ -1147,11 +1146,11 @@ func (api *API) oidcGroups(ctx context.Context, mergedClaims map[string]interfac
1147
1146
if len (groups ) == 0 {
1148
1147
detail = "You are currently not a member of any groups! Ask an administrator to add you to an authorized group to login."
1149
1148
}
1150
- return usingGroups , groups , & httpError {
1151
- code : http .StatusForbidden ,
1152
- msg : "Not a member of an allowed group" ,
1153
- detail : detail ,
1154
- renderStaticPage : true ,
1149
+ return usingGroups , groups , & idpsync. HttpError {
1150
+ Code : http .StatusForbidden ,
1151
+ Msg : "Not a member of an allowed group" ,
1152
+ Detail : detail ,
1153
+ RenderStaticPage : true ,
1155
1154
}
1156
1155
}
1157
1156
}
@@ -1171,7 +1170,7 @@ func (api *API) oidcGroups(ctx context.Context, mergedClaims map[string]interfac
1171
1170
// It would be preferred to just return an error, however this function
1172
1171
// decorates returned errors with the appropriate HTTP status codes and details
1173
1172
// that are hard to carry in a standard `error` without more work.
1174
- func (api * API ) oidcRoles (ctx context.Context , mergedClaims map [string ]interface {}) ([]string , * httpError ) {
1173
+ func (api * API ) oidcRoles (ctx context.Context , mergedClaims map [string ]interface {}) ([]string , * idpsync. HttpError ) {
1175
1174
roles := api .OIDCConfig .UserRolesDefault
1176
1175
if ! api .OIDCConfig .RoleSyncEnabled () {
1177
1176
return roles , nil
@@ -1193,11 +1192,11 @@ func (api *API) oidcRoles(ctx context.Context, mergedClaims map[string]interface
1193
1192
slog .F ("type" , fmt .Sprintf ("%T" , rolesRow )),
1194
1193
slog .Error (err ),
1195
1194
)
1196
- return nil , & httpError {
1197
- code : http .StatusInternalServerError ,
1198
- msg : "Login disabled until OIDC config is fixed" ,
1199
- detail : fmt .Sprintf ("Roles claim must be an array of strings, type found: %T. Disabling role sync will allow login to proceed." , rolesRow ),
1200
- renderStaticPage : false ,
1195
+ return nil , & idpsync. HttpError {
1196
+ Code : http .StatusInternalServerError ,
1197
+ Msg : "Login disabled until OIDC config is fixed" ,
1198
+ Detail : fmt .Sprintf ("Roles claim must be an array of strings, type found: %T. Disabling role sync will allow login to proceed." , rolesRow ),
1199
+ RenderStaticPage : false ,
1201
1200
}
1202
1201
}
1203
1202
@@ -1318,43 +1317,6 @@ func (p *oauthLoginParams) CommitAuditLogs() {
1318
1317
}
1319
1318
}
1320
1319
1321
- type httpError struct {
1322
- code int
1323
- msg string
1324
- detail string
1325
- renderStaticPage bool
1326
-
1327
- renderDetailMarkdown bool
1328
- }
1329
-
1330
- func (e httpError ) Write (rw http.ResponseWriter , r * http.Request ) {
1331
- if e .renderStaticPage {
1332
- site .RenderStaticErrorPage (rw , r , site.ErrorPageData {
1333
- Status : e .code ,
1334
- HideStatus : true ,
1335
- Title : e .msg ,
1336
- Description : e .detail ,
1337
- RetryEnabled : false ,
1338
- DashboardURL : "/login" ,
1339
-
1340
- RenderDescriptionMarkdown : e .renderDetailMarkdown ,
1341
- })
1342
- return
1343
- }
1344
- httpapi .Write (r .Context (), rw , e .code , codersdk.Response {
1345
- Message : e .msg ,
1346
- Detail : e .detail ,
1347
- })
1348
- }
1349
-
1350
- func (e httpError ) Error () string {
1351
- if e .detail != "" {
1352
- return e .detail
1353
- }
1354
-
1355
- return e .msg
1356
- }
1357
-
1358
1320
func (api * API ) oauthLogin (r * http.Request , params * oauthLoginParams ) ([]* http.Cookie , database.User , database.APIKey , error ) {
1359
1321
var (
1360
1322
ctx = r .Context ()
@@ -1391,13 +1353,12 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
1391
1353
if api .OIDCConfig != nil && api .OIDCConfig .SignupsDisabledText != "" {
1392
1354
signupsDisabledText = render .HTMLFromMarkdown (api .OIDCConfig .SignupsDisabledText )
1393
1355
}
1394
- return httpError {
1395
- code : http .StatusForbidden ,
1396
- msg : "Signups are disabled" ,
1397
- detail : signupsDisabledText ,
1398
- renderStaticPage : true ,
1399
-
1400
- renderDetailMarkdown : true ,
1356
+ return & idpsync.HttpError {
1357
+ Code : http .StatusForbidden ,
1358
+ Msg : "Signups are disabled" ,
1359
+ Detail : signupsDisabledText ,
1360
+ RenderStaticPage : true ,
1361
+ RenderDetailMarkdown : true ,
1401
1362
}
1402
1363
}
1403
1364
@@ -1443,9 +1404,9 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
1443
1404
}
1444
1405
}
1445
1406
if ! validUsername {
1446
- return httpError {
1447
- code : http .StatusConflict ,
1448
- msg : fmt .Sprintf ("exhausted alternatives for taken username %q" , original ),
1407
+ return & idpsync. HttpError {
1408
+ Code : http .StatusConflict ,
1409
+ Msg : fmt .Sprintf ("exhausted alternatives for taken username %q" , original ),
1449
1410
}
1450
1411
}
1451
1412
}
@@ -1586,11 +1547,11 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
1586
1547
//nolint:gocritic
1587
1548
err := api .Options .SetUserSiteRoles (dbauthz .AsSystemRestricted (ctx ), logger , tx , user .ID , filtered )
1588
1549
if err != nil {
1589
- return httpError {
1590
- code : http .StatusBadRequest ,
1591
- msg : "Invalid roles through OIDC claims" ,
1592
- detail : fmt .Sprintf ("Error from role assignment attempt: %s" , err .Error ()),
1593
- renderStaticPage : true ,
1550
+ return & idpsync. HttpError {
1551
+ Code : http .StatusBadRequest ,
1552
+ Msg : "Invalid roles through OIDC claims" ,
1553
+ Detail : fmt .Sprintf ("Error from role assignment attempt: %s" , err .Error ()),
1554
+ RenderStaticPage : true ,
1594
1555
}
1595
1556
}
1596
1557
if len (ignored ) > 0 {
@@ -1701,17 +1662,17 @@ func (api *API) convertUserToOauth(ctx context.Context, r *http.Request, db data
1701
1662
// Trying to convert to OIDC, but the email does not match.
1702
1663
// So do not make a new user, just block the request.
1703
1664
if user .ID == uuid .Nil {
1704
- return database.User {}, httpError {
1705
- code : http .StatusBadRequest ,
1706
- msg : fmt .Sprintf ("The oidc account with the email %q does not match the email of the account you are trying to convert. Contact your administrator to resolve this issue." , params .Email ),
1665
+ return database.User {}, idpsync. HttpError {
1666
+ Code : http .StatusBadRequest ,
1667
+ Msg : fmt .Sprintf ("The oidc account with the email %q does not match the email of the account you are trying to convert. Contact your administrator to resolve this issue." , params .Email ),
1707
1668
}
1708
1669
}
1709
1670
1710
1671
jwtCookie , err := r .Cookie (OAuthConvertCookieValue )
1711
1672
if err != nil {
1712
- return database.User {}, httpError {
1713
- code : http .StatusBadRequest ,
1714
- msg : fmt .Sprintf ("Convert to oauth cookie not found. Missing signed jwt to authorize this action. " +
1673
+ return database.User {}, idpsync. HttpError {
1674
+ Code : http .StatusBadRequest ,
1675
+ Msg : fmt .Sprintf ("Convert to oauth cookie not found. Missing signed jwt to authorize this action. " +
1715
1676
"Please try again." ),
1716
1677
}
1717
1678
}
@@ -1721,15 +1682,15 @@ func (api *API) convertUserToOauth(ctx context.Context, r *http.Request, db data
1721
1682
})
1722
1683
if xerrors .Is (err , jwt .ErrSignatureInvalid ) || ! token .Valid {
1723
1684
// These errors are probably because the user is mixing 2 coder deployments.
1724
- return database.User {}, httpError {
1725
- code : http .StatusBadRequest ,
1726
- msg : "Using an invalid jwt to authorize this action. Ensure there is only 1 coder deployment and try again." ,
1685
+ return database.User {}, idpsync. HttpError {
1686
+ Code : http .StatusBadRequest ,
1687
+ Msg : "Using an invalid jwt to authorize this action. Ensure there is only 1 coder deployment and try again." ,
1727
1688
}
1728
1689
}
1729
1690
if err != nil {
1730
- return database.User {}, httpError {
1731
- code : http .StatusInternalServerError ,
1732
- msg : fmt .Sprintf ("Error parsing jwt: %v" , err ),
1691
+ return database.User {}, idpsync. HttpError {
1692
+ Code : http .StatusInternalServerError ,
1693
+ Msg : fmt .Sprintf ("Error parsing jwt: %v" , err ),
1733
1694
}
1734
1695
}
1735
1696
@@ -1749,16 +1710,16 @@ func (api *API) convertUserToOauth(ctx context.Context, r *http.Request, db data
1749
1710
oauthConvertAudit .Old = user
1750
1711
1751
1712
if claims .RegisteredClaims .Issuer != api .DeploymentID {
1752
- return database.User {}, httpError {
1753
- code : http .StatusForbidden ,
1754
- msg : "Request to convert login type failed. Issuer mismatch. Found a cookie from another coder deployment, please try again." ,
1713
+ return database.User {}, idpsync. HttpError {
1714
+ Code : http .StatusForbidden ,
1715
+ Msg : "Request to convert login type failed. Issuer mismatch. Found a cookie from another coder deployment, please try again." ,
1755
1716
}
1756
1717
}
1757
1718
1758
1719
if params .State .StateString != claims .State {
1759
- return database.User {}, httpError {
1760
- code : http .StatusForbidden ,
1761
- msg : "Request to convert login type failed. State mismatch." ,
1720
+ return database.User {}, idpsync. HttpError {
1721
+ Code : http .StatusForbidden ,
1722
+ Msg : "Request to convert login type failed. State mismatch." ,
1762
1723
}
1763
1724
}
1764
1725
@@ -1768,9 +1729,9 @@ func (api *API) convertUserToOauth(ctx context.Context, r *http.Request, db data
1768
1729
if user .ID != claims .UserID ||
1769
1730
codersdk .LoginType (user .LoginType ) != claims .FromLoginType ||
1770
1731
codersdk .LoginType (params .LoginType ) != claims .ToLoginType {
1771
- return database.User {}, httpError {
1772
- code : http .StatusForbidden ,
1773
- msg : fmt .Sprintf ("Request to convert login type from %s to %s failed" , user .LoginType , params .LoginType ),
1732
+ return database.User {}, idpsync. HttpError {
1733
+ Code : http .StatusForbidden ,
1734
+ Msg : fmt .Sprintf ("Request to convert login type from %s to %s failed" , user .LoginType , params .LoginType ),
1774
1735
}
1775
1736
}
1776
1737
@@ -1784,9 +1745,9 @@ func (api *API) convertUserToOauth(ctx context.Context, r *http.Request, db data
1784
1745
UserID : user .ID ,
1785
1746
})
1786
1747
if err != nil {
1787
- return database.User {}, httpError {
1788
- code : http .StatusInternalServerError ,
1789
- msg : "Failed to convert user to new login type" ,
1748
+ return database.User {}, idpsync. HttpError {
1749
+ Code : http .StatusInternalServerError ,
1750
+ Msg : "Failed to convert user to new login type" ,
1790
1751
}
1791
1752
}
1792
1753
oauthConvertAudit .New = user
@@ -1872,16 +1833,16 @@ func clearOAuthConvertCookie() *http.Cookie {
1872
1833
}
1873
1834
}
1874
1835
1875
- func wrongLoginTypeHTTPError (user database.LoginType , params database.LoginType ) httpError {
1836
+ func wrongLoginTypeHTTPError (user database.LoginType , params database.LoginType ) idpsync. HttpError {
1876
1837
addedMsg := ""
1877
1838
if user == database .LoginTypePassword {
1878
1839
addedMsg = " You can convert your account to use this login type by visiting your account settings."
1879
1840
}
1880
- return httpError {
1881
- code : http .StatusForbidden ,
1882
- renderStaticPage : true ,
1883
- msg : "Incorrect login type" ,
1884
- detail : fmt .Sprintf ("Attempting to use login type %q, but the user has the login type %q.%s" ,
1841
+ return idpsync. HttpError {
1842
+ Code : http .StatusForbidden ,
1843
+ RenderStaticPage : true ,
1844
+ Msg : "Incorrect login type" ,
1845
+ Detail : fmt .Sprintf ("Attempting to use login type %q, but the user has the login type %q.%s" ,
1885
1846
params , user , addedMsg ),
1886
1847
}
1887
1848
}
0 commit comments