mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add endpoint and CLI for users to view their own OIDC claims (#23053)
- Adds a new API endpoint `GET /api/v2/users/oidc-claims` that returns only the **merged claims** (not the separate id_token/userinfo breakdown). Scoped exclusively to the authenticated user's own identity — no user parameter, so users cannot view each other's claims. - Adds a new CLI command:** `coder users oidc-claims` that hits the above endpoint. - The existing owner-only debug endpoint is preserved unchanged for admins who need the full claim breakdown. > 🤖 This PR was created with the help of Coder Agents, and will be reviewed by my human. 🧑💻
This commit is contained in:
@@ -72,6 +72,64 @@ func (api *API) userDebugOIDC(rw http.ResponseWriter, r *http.Request) {
|
||||
httpapi.Write(ctx, rw, http.StatusOK, link.Claims)
|
||||
}
|
||||
|
||||
// Returns the merged OIDC claims for the authenticated user.
|
||||
//
|
||||
// @Summary Get OIDC claims for the authenticated user
|
||||
// @ID get-oidc-claims-for-the-authenticated-user
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags Users
|
||||
// @Success 200 {object} codersdk.OIDCClaimsResponse
|
||||
// @Router /users/oidc-claims [get]
|
||||
func (api *API) userOIDCClaims(rw http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
apiKey = httpmw.APIKey(r)
|
||||
)
|
||||
|
||||
user, err := api.Database.GetUserByID(ctx, apiKey.UserID)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Failed to get user.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if user.LoginType != database.LoginTypeOIDC {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "User is not an OIDC user.",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
//nolint:gocritic // GetUserLinkByUserIDLoginType requires reading
|
||||
// rbac.ResourceSystem. The endpoint is scoped to the authenticated
|
||||
// user's own identity via apiKey, so this is safe.
|
||||
link, err := api.Database.GetUserLinkByUserIDLoginType(
|
||||
dbauthz.AsSystemRestricted(ctx),
|
||||
database.GetUserLinkByUserIDLoginTypeParams{
|
||||
UserID: user.ID,
|
||||
LoginType: database.LoginTypeOIDC,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Failed to get user link.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
claims := link.Claims.MergedClaims
|
||||
if claims == nil {
|
||||
claims = map[string]interface{}{}
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusOK, codersdk.OIDCClaimsResponse{
|
||||
Claims: claims,
|
||||
})
|
||||
}
|
||||
|
||||
// Returns whether the initial user has been created or not.
|
||||
//
|
||||
// @Summary Check initial user created
|
||||
|
||||
Reference in New Issue
Block a user