mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: implement user link claims as a typed golang object (#15502)
Move claims from a `debug` column to an actual typed column to be used. This does not functionally change anything, it just adds some Go typing to build on.
This commit is contained in:
@@ -3,7 +3,6 @@ package oidctest
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
@@ -89,7 +88,7 @@ func (*LoginHelper) ExpireOauthToken(t *testing.T, db database.Store, user *code
|
||||
OAuthExpiry: time.Now().Add(time.Hour * -1),
|
||||
UserID: link.UserID,
|
||||
LoginType: link.LoginType,
|
||||
DebugContext: json.RawMessage("{}"),
|
||||
Claims: database.UserLinkClaims{},
|
||||
})
|
||||
require.NoError(t, err, "expire user link")
|
||||
|
||||
|
||||
@@ -1281,7 +1281,7 @@ func (s *MethodTestSuite) TestUser() {
|
||||
OAuthExpiry: link.OAuthExpiry,
|
||||
UserID: link.UserID,
|
||||
LoginType: link.LoginType,
|
||||
DebugContext: json.RawMessage("{}"),
|
||||
Claims: database.UserLinkClaims{},
|
||||
}).Asserts(rbac.ResourceUserObject(link.UserID), policy.ActionUpdatePersonal).Returns(link)
|
||||
}))
|
||||
s.Run("UpdateUserRoles", s.Subtest(func(db database.Store, check *expects) {
|
||||
|
||||
@@ -726,7 +726,7 @@ func UserLink(t testing.TB, db database.Store, orig database.UserLink) database.
|
||||
OAuthRefreshToken: takeFirst(orig.OAuthRefreshToken, uuid.NewString()),
|
||||
OAuthRefreshTokenKeyID: takeFirst(orig.OAuthRefreshTokenKeyID, sql.NullString{}),
|
||||
OAuthExpiry: takeFirst(orig.OAuthExpiry, dbtime.Now().Add(time.Hour*24)),
|
||||
DebugContext: takeFirstSlice(orig.DebugContext, json.RawMessage("{}")),
|
||||
Claims: orig.Claims,
|
||||
})
|
||||
|
||||
require.NoError(t, err, "insert link")
|
||||
|
||||
@@ -7857,7 +7857,7 @@ func (q *FakeQuerier) InsertUserLink(_ context.Context, args database.InsertUser
|
||||
OAuthRefreshToken: args.OAuthRefreshToken,
|
||||
OAuthRefreshTokenKeyID: args.OAuthRefreshTokenKeyID,
|
||||
OAuthExpiry: args.OAuthExpiry,
|
||||
DebugContext: args.DebugContext,
|
||||
Claims: args.Claims,
|
||||
}
|
||||
|
||||
q.userLinks = append(q.userLinks, link)
|
||||
@@ -9318,7 +9318,7 @@ func (q *FakeQuerier) UpdateUserLink(_ context.Context, params database.UpdateUs
|
||||
link.OAuthRefreshToken = params.OAuthRefreshToken
|
||||
link.OAuthRefreshTokenKeyID = params.OAuthRefreshTokenKeyID
|
||||
link.OAuthExpiry = params.OAuthExpiry
|
||||
link.DebugContext = params.DebugContext
|
||||
link.Claims = params.Claims
|
||||
|
||||
q.userLinks[i] = link
|
||||
return link, nil
|
||||
|
||||
Generated
+2
-2
@@ -1337,14 +1337,14 @@ CREATE TABLE user_links (
|
||||
oauth_expiry timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL,
|
||||
oauth_access_token_key_id text,
|
||||
oauth_refresh_token_key_id text,
|
||||
debug_context jsonb DEFAULT '{}'::jsonb NOT NULL
|
||||
claims jsonb DEFAULT '{}'::jsonb NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN user_links.oauth_access_token_key_id IS 'The ID of the key used to encrypt the OAuth access token. If this is NULL, the access token is not encrypted';
|
||||
|
||||
COMMENT ON COLUMN user_links.oauth_refresh_token_key_id IS 'The ID of the key used to encrypt the OAuth refresh token. If this is NULL, the refresh token is not encrypted';
|
||||
|
||||
COMMENT ON COLUMN user_links.debug_context IS 'Debug information includes information like id_token and userinfo claims.';
|
||||
COMMENT ON COLUMN user_links.claims IS 'Claims from the IDP for the linked user. Includes both id_token and userinfo claims. ';
|
||||
|
||||
CREATE TABLE workspace_agent_log_sources (
|
||||
workspace_agent_id uuid NOT NULL,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE user_links RENAME COLUMN claims TO debug_context;
|
||||
|
||||
COMMENT ON COLUMN user_links.debug_context IS 'Debug information includes information like id_token and userinfo claims.';
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE user_links RENAME COLUMN debug_context TO claims;
|
||||
|
||||
COMMENT ON COLUMN user_links.claims IS 'Claims from the IDP for the linked user. Includes both id_token and userinfo claims. ';
|
||||
@@ -2892,8 +2892,8 @@ type UserLink struct {
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
// The ID of the key used to encrypt the OAuth refresh token. If this is NULL, the refresh token is not encrypted
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
// Debug information includes information like id_token and userinfo claims.
|
||||
DebugContext json.RawMessage `db:"debug_context" json:"debug_context"`
|
||||
// Claims from the IDP for the linked user. Includes both id_token and userinfo claims.
|
||||
Claims UserLinkClaims `db:"claims" json:"claims"`
|
||||
}
|
||||
|
||||
// Visible fields of users are allowed to be joined with other tables for including context of other resources.
|
||||
|
||||
@@ -9689,7 +9689,7 @@ func (q *sqlQuerier) InsertTemplateVersionWorkspaceTag(ctx context.Context, arg
|
||||
|
||||
const getUserLinkByLinkedID = `-- name: GetUserLinkByLinkedID :one
|
||||
SELECT
|
||||
user_links.user_id, user_links.login_type, user_links.linked_id, user_links.oauth_access_token, user_links.oauth_refresh_token, user_links.oauth_expiry, user_links.oauth_access_token_key_id, user_links.oauth_refresh_token_key_id, user_links.debug_context
|
||||
user_links.user_id, user_links.login_type, user_links.linked_id, user_links.oauth_access_token, user_links.oauth_refresh_token, user_links.oauth_expiry, user_links.oauth_access_token_key_id, user_links.oauth_refresh_token_key_id, user_links.claims
|
||||
FROM
|
||||
user_links
|
||||
INNER JOIN
|
||||
@@ -9712,14 +9712,14 @@ func (q *sqlQuerier) GetUserLinkByLinkedID(ctx context.Context, linkedID string)
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserLinkByUserIDLoginType = `-- name: GetUserLinkByUserIDLoginType :one
|
||||
SELECT
|
||||
user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
FROM
|
||||
user_links
|
||||
WHERE
|
||||
@@ -9743,13 +9743,13 @@ func (q *sqlQuerier) GetUserLinkByUserIDLoginType(ctx context.Context, arg GetUs
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getUserLinksByUserID = `-- name: GetUserLinksByUserID :many
|
||||
SELECT user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context FROM user_links WHERE user_id = $1
|
||||
SELECT user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims FROM user_links WHERE user_id = $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetUserLinksByUserID(ctx context.Context, userID uuid.UUID) ([]UserLink, error) {
|
||||
@@ -9770,7 +9770,7 @@ func (q *sqlQuerier) GetUserLinksByUserID(ctx context.Context, userID uuid.UUID)
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -9796,22 +9796,22 @@ INSERT INTO
|
||||
oauth_refresh_token,
|
||||
oauth_refresh_token_key_id,
|
||||
oauth_expiry,
|
||||
debug_context
|
||||
claims
|
||||
)
|
||||
VALUES
|
||||
( $1, $2, $3, $4, $5, $6, $7, $8, $9 ) RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
( $1, $2, $3, $4, $5, $6, $7, $8, $9 ) RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
`
|
||||
|
||||
type InsertUserLinkParams struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
LinkedID string `db:"linked_id" json:"linked_id"`
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
DebugContext json.RawMessage `db:"debug_context" json:"debug_context"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
LinkedID string `db:"linked_id" json:"linked_id"`
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
Claims UserLinkClaims `db:"claims" json:"claims"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertUserLink(ctx context.Context, arg InsertUserLinkParams) (UserLink, error) {
|
||||
@@ -9824,7 +9824,7 @@ func (q *sqlQuerier) InsertUserLink(ctx context.Context, arg InsertUserLinkParam
|
||||
arg.OAuthRefreshToken,
|
||||
arg.OAuthRefreshTokenKeyID,
|
||||
arg.OAuthExpiry,
|
||||
arg.DebugContext,
|
||||
arg.Claims,
|
||||
)
|
||||
var i UserLink
|
||||
err := row.Scan(
|
||||
@@ -9836,7 +9836,7 @@ func (q *sqlQuerier) InsertUserLink(ctx context.Context, arg InsertUserLinkParam
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -9850,20 +9850,20 @@ SET
|
||||
oauth_refresh_token = $3,
|
||||
oauth_refresh_token_key_id = $4,
|
||||
oauth_expiry = $5,
|
||||
debug_context = $6
|
||||
claims = $6
|
||||
WHERE
|
||||
user_id = $7 AND login_type = $8 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
user_id = $7 AND login_type = $8 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
`
|
||||
|
||||
type UpdateUserLinkParams struct {
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
DebugContext json.RawMessage `db:"debug_context" json:"debug_context"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
OAuthAccessToken string `db:"oauth_access_token" json:"oauth_access_token"`
|
||||
OAuthAccessTokenKeyID sql.NullString `db:"oauth_access_token_key_id" json:"oauth_access_token_key_id"`
|
||||
OAuthRefreshToken string `db:"oauth_refresh_token" json:"oauth_refresh_token"`
|
||||
OAuthRefreshTokenKeyID sql.NullString `db:"oauth_refresh_token_key_id" json:"oauth_refresh_token_key_id"`
|
||||
OAuthExpiry time.Time `db:"oauth_expiry" json:"oauth_expiry"`
|
||||
Claims UserLinkClaims `db:"claims" json:"claims"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
LoginType LoginType `db:"login_type" json:"login_type"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateUserLink(ctx context.Context, arg UpdateUserLinkParams) (UserLink, error) {
|
||||
@@ -9873,7 +9873,7 @@ func (q *sqlQuerier) UpdateUserLink(ctx context.Context, arg UpdateUserLinkParam
|
||||
arg.OAuthRefreshToken,
|
||||
arg.OAuthRefreshTokenKeyID,
|
||||
arg.OAuthExpiry,
|
||||
arg.DebugContext,
|
||||
arg.Claims,
|
||||
arg.UserID,
|
||||
arg.LoginType,
|
||||
)
|
||||
@@ -9887,7 +9887,7 @@ func (q *sqlQuerier) UpdateUserLink(ctx context.Context, arg UpdateUserLinkParam
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@@ -9898,7 +9898,7 @@ UPDATE
|
||||
SET
|
||||
linked_id = $1
|
||||
WHERE
|
||||
user_id = $2 AND login_type = $3 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, debug_context
|
||||
user_id = $2 AND login_type = $3 RETURNING user_id, login_type, linked_id, oauth_access_token, oauth_refresh_token, oauth_expiry, oauth_access_token_key_id, oauth_refresh_token_key_id, claims
|
||||
`
|
||||
|
||||
type UpdateUserLinkedIDParams struct {
|
||||
@@ -9919,7 +9919,7 @@ func (q *sqlQuerier) UpdateUserLinkedID(ctx context.Context, arg UpdateUserLinke
|
||||
&i.OAuthExpiry,
|
||||
&i.OAuthAccessTokenKeyID,
|
||||
&i.OAuthRefreshTokenKeyID,
|
||||
&i.DebugContext,
|
||||
&i.Claims,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ INSERT INTO
|
||||
oauth_refresh_token,
|
||||
oauth_refresh_token_key_id,
|
||||
oauth_expiry,
|
||||
debug_context
|
||||
claims
|
||||
)
|
||||
VALUES
|
||||
( $1, $2, $3, $4, $5, $6, $7, $8, $9 ) RETURNING *;
|
||||
@@ -54,6 +54,6 @@ SET
|
||||
oauth_refresh_token = $3,
|
||||
oauth_refresh_token_key_id = $4,
|
||||
oauth_expiry = $5,
|
||||
debug_context = $6
|
||||
claims = $6
|
||||
WHERE
|
||||
user_id = $7 AND login_type = $8 RETURNING *;
|
||||
|
||||
@@ -79,6 +79,9 @@ sql:
|
||||
- column: "provisioner_job_stats.*_secs"
|
||||
go_type:
|
||||
type: "float64"
|
||||
- column: "user_links.claims"
|
||||
go_type:
|
||||
type: "UserLinkClaims"
|
||||
rename:
|
||||
group_member: GroupMemberTable
|
||||
group_members_expanded: GroupMember
|
||||
|
||||
@@ -207,3 +207,25 @@ func (p *AgentIDNamePair) Scan(src interface{}) error {
|
||||
func (p AgentIDNamePair) Value() (driver.Value, error) {
|
||||
return fmt.Sprintf(`(%s,%s)`, p.ID.String(), p.Name), nil
|
||||
}
|
||||
|
||||
// UserLinkClaims is the returned IDP claims for a given user link.
|
||||
// These claims are fetched at login time. These are the claims that were
|
||||
// used for IDP sync.
|
||||
type UserLinkClaims struct {
|
||||
IDTokenClaims map[string]interface{} `json:"id_token_claims"`
|
||||
UserInfoClaims map[string]interface{} `json:"user_info_claims"`
|
||||
}
|
||||
|
||||
func (a *UserLinkClaims) Scan(src interface{}) error {
|
||||
switch v := src.(type) {
|
||||
case string:
|
||||
return json.Unmarshal([]byte(v), &a)
|
||||
case []byte:
|
||||
return json.Unmarshal(v, &a)
|
||||
}
|
||||
return xerrors.Errorf("unexpected type %T", src)
|
||||
}
|
||||
|
||||
func (a UserLinkClaims) Value() (driver.Value, error) {
|
||||
return json.Marshal(a)
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ func ExtractAPIKey(rw http.ResponseWriter, r *http.Request, cfg ExtractAPIKeyCon
|
||||
OAuthExpiry: link.OAuthExpiry,
|
||||
// Refresh should keep the same debug context because we use
|
||||
// the original claims for the group/role sync.
|
||||
DebugContext: link.DebugContext,
|
||||
Claims: link.Claims,
|
||||
})
|
||||
if err != nil {
|
||||
return write(http.StatusInternalServerError, codersdk.Response{
|
||||
|
||||
@@ -2083,7 +2083,7 @@ func obtainOIDCAccessToken(ctx context.Context, db database.Store, oidcConfig pr
|
||||
OAuthRefreshToken: link.OAuthRefreshToken,
|
||||
OAuthRefreshTokenKeyID: sql.NullString{}, // set by dbcrypt if required
|
||||
OAuthExpiry: link.OAuthExpiry,
|
||||
DebugContext: link.DebugContext,
|
||||
Claims: link.Claims,
|
||||
})
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("update user link: %w", err)
|
||||
|
||||
+7
-11
@@ -3,7 +3,6 @@ package coderd
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -966,7 +965,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
|
||||
Username: username,
|
||||
AvatarURL: ghUser.GetAvatarURL(),
|
||||
Name: normName,
|
||||
DebugContext: OauthDebugContext{},
|
||||
UserClaims: database.UserLinkClaims{},
|
||||
GroupSync: idpsync.GroupParams{
|
||||
SyncEntitled: false,
|
||||
},
|
||||
@@ -1324,7 +1323,7 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
|
||||
OrganizationSync: orgSync,
|
||||
GroupSync: groupSync,
|
||||
RoleSync: roleSync,
|
||||
DebugContext: OauthDebugContext{
|
||||
UserClaims: database.UserLinkClaims{
|
||||
IDTokenClaims: idtokenClaims,
|
||||
UserInfoClaims: userInfoClaims,
|
||||
},
|
||||
@@ -1421,7 +1420,9 @@ type oauthLoginParams struct {
|
||||
GroupSync idpsync.GroupParams
|
||||
RoleSync idpsync.RoleParams
|
||||
|
||||
DebugContext OauthDebugContext
|
||||
// UserClaims should only be populated for OIDC logins.
|
||||
// It is used to save the user's claims on login.
|
||||
UserClaims database.UserLinkClaims
|
||||
|
||||
commitLock sync.Mutex
|
||||
initAuditRequest func(params *audit.RequestParams) *audit.Request[database.User]
|
||||
@@ -1591,11 +1592,6 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
|
||||
dormantConvertAudit.New = user
|
||||
}
|
||||
|
||||
debugContext, err := json.Marshal(params.DebugContext)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("marshal debug context: %w", err)
|
||||
}
|
||||
|
||||
if link.UserID == uuid.Nil {
|
||||
//nolint:gocritic // System needs to insert the user link (linked_id, oauth_token, oauth_expiry).
|
||||
link, err = tx.InsertUserLink(dbauthz.AsSystemRestricted(ctx), database.InsertUserLinkParams{
|
||||
@@ -1607,7 +1603,7 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
|
||||
OAuthRefreshToken: params.State.Token.RefreshToken,
|
||||
OAuthRefreshTokenKeyID: sql.NullString{}, // set by dbcrypt if required
|
||||
OAuthExpiry: params.State.Token.Expiry,
|
||||
DebugContext: debugContext,
|
||||
Claims: params.UserClaims,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert user link: %w", err)
|
||||
@@ -1624,7 +1620,7 @@ func (api *API) oauthLogin(r *http.Request, params *oauthLoginParams) ([]*http.C
|
||||
OAuthRefreshToken: params.State.Token.RefreshToken,
|
||||
OAuthRefreshTokenKeyID: sql.NullString{}, // set by dbcrypt if required
|
||||
OAuthExpiry: params.State.Token.Expiry,
|
||||
DebugContext: debugContext,
|
||||
Claims: params.UserClaims,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("update user link: %w", err)
|
||||
|
||||
@@ -843,7 +843,7 @@ func TestUserOAuth2Github(t *testing.T) {
|
||||
OAuthAccessToken: "random",
|
||||
OAuthRefreshToken: "random",
|
||||
OAuthExpiry: time.Now(),
|
||||
DebugContext: []byte(`{}`),
|
||||
Claims: database.UserLinkClaims{},
|
||||
})
|
||||
require.ErrorContains(t, err, "Cannot create user_link for deleted user")
|
||||
|
||||
|
||||
+1
-2
@@ -70,8 +70,7 @@ func (api *API) userDebugOIDC(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// This will encode properly because it is a json.RawMessage.
|
||||
httpapi.Write(ctx, rw, http.StatusOK, link.DebugContext)
|
||||
httpapi.Write(ctx, rw, http.StatusOK, link.Claims)
|
||||
}
|
||||
|
||||
// Returns whether the initial user has been created or not.
|
||||
|
||||
@@ -43,7 +43,7 @@ func Rotate(ctx context.Context, log slog.Logger, sqlDB *sql.DB, ciphers []Ciphe
|
||||
OAuthExpiry: userLink.OAuthExpiry,
|
||||
UserID: uid,
|
||||
LoginType: userLink.LoginType,
|
||||
DebugContext: userLink.DebugContext,
|
||||
Claims: userLink.Claims,
|
||||
}); err != nil {
|
||||
return xerrors.Errorf("update user link user_id=%s linked_id=%s: %w", userLink.UserID, userLink.LinkedID, err)
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func Decrypt(ctx context.Context, log slog.Logger, sqlDB *sql.DB, ciphers []Ciph
|
||||
OAuthExpiry: userLink.OAuthExpiry,
|
||||
UserID: uid,
|
||||
LoginType: userLink.LoginType,
|
||||
DebugContext: userLink.DebugContext,
|
||||
Claims: userLink.Claims,
|
||||
}); err != nil {
|
||||
return xerrors.Errorf("update user link user_id=%s linked_id=%s: %w", userLink.UserID, userLink.LinkedID, err)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -52,12 +51,27 @@ func TestUserLinks(t *testing.T) {
|
||||
UserID: user.ID,
|
||||
})
|
||||
|
||||
expectedClaims := database.UserLinkClaims{
|
||||
IDTokenClaims: map[string]interface{}{
|
||||
"sub": "123",
|
||||
"groups": []interface{}{
|
||||
"foo", "bar",
|
||||
},
|
||||
},
|
||||
UserInfoClaims: map[string]interface{}{
|
||||
"number": float64(2),
|
||||
"struct": map[string]interface{}{
|
||||
"number": float64(2),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
updated, err := crypt.UpdateUserLink(ctx, database.UpdateUserLinkParams{
|
||||
OAuthAccessToken: "access",
|
||||
OAuthRefreshToken: "refresh",
|
||||
UserID: link.UserID,
|
||||
LoginType: link.LoginType,
|
||||
DebugContext: json.RawMessage("{}"),
|
||||
Claims: expectedClaims,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "access", updated.OAuthAccessToken)
|
||||
@@ -69,6 +83,7 @@ func TestUserLinks(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
requireEncryptedEquals(t, ciphers[0], rawLink.OAuthAccessToken, "access")
|
||||
requireEncryptedEquals(t, ciphers[0], rawLink.OAuthRefreshToken, "refresh")
|
||||
require.EqualValues(t, expectedClaims, rawLink.Claims)
|
||||
})
|
||||
|
||||
t.Run("GetUserLinkByLinkedID", func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user