Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: access tokens for service users and refresh token infos #1779

Merged
merged 4 commits into from May 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 13 additions & 11 deletions internal/api/oidc/auth_request.go
Expand Up @@ -110,17 +110,7 @@ func grantsToScopes(grants []*grant_model.UserGrantView) []string {
func (o *OPStorage) CreateAccessAndRefreshTokens(ctx context.Context, req op.TokenRequest, refreshToken string) (_, _ string, _ time.Time, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
var userAgentID, applicationID, userOrgID string
var authTime time.Time
var authMethodsReferences []string
authReq, ok := req.(*AuthRequest)
if ok {
userAgentID = authReq.AgentID
applicationID = authReq.ApplicationID
userOrgID = authReq.UserOrgID
authTime = authReq.AuthTime
authMethodsReferences = authReq.GetAMR()
}
userAgentID, applicationID, userOrgID, authTime, authMethodsReferences := getInfoFromRequest(req)
resp, token, err := o.command.AddAccessAndRefreshToken(ctx, userOrgID, userAgentID, applicationID, req.GetSubject(),
refreshToken, req.GetAudience(), req.GetScopes(), authMethodsReferences, o.defaultAccessTokenLifetime,
o.defaultRefreshTokenIdleExpiration, o.defaultRefreshTokenExpiration, authTime) //PLANNED: lifetime from client
Expand All @@ -130,6 +120,18 @@ func (o *OPStorage) CreateAccessAndRefreshTokens(ctx context.Context, req op.Tok
return resp.TokenID, token, resp.Expiration, nil
}

func getInfoFromRequest(req op.TokenRequest) (string, string, string, time.Time, []string) {
authReq, ok := req.(*AuthRequest)
if ok {
return authReq.AgentID, authReq.ApplicationID, authReq.UserOrgID, authReq.AuthTime, authReq.GetAMR()
}
refreshReq, ok := req.(*RefreshTokenRequest)
if ok {
return refreshReq.UserAgentID, refreshReq.ClientID, "", refreshReq.AuthTime, refreshReq.AuthMethodsReferences
}
return "", "", "", time.Time{}, nil
}

func (o *OPStorage) TokenRequestByRefreshToken(ctx context.Context, refreshToken string) (op.RefreshTokenRequest, error) {
tokenView, err := o.repo.RefreshTokenByID(ctx, refreshToken)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/command/user.go
Expand Up @@ -211,7 +211,7 @@ func (c *Commands) RemoveUser(ctx context.Context, userID, resourceOwner string,
}

func (c *Commands) AddUserToken(ctx context.Context, orgID, agentID, clientID, userID string, audience, scopes []string, lifetime time.Duration) (*domain.Token, error) {
if orgID == "" || userID == "" {
if userID == "" { //do not check for empty orgID (JWT Profile requests won't provide it, so service user requests fail)
return nil, caos_errs.ThrowInvalidArgument(nil, "COMMAND-Dbge4", "Errors.IDMissing")
}
userWriteModel := NewUserWriteModel(userID, orgID)
Expand Down
8 changes: 4 additions & 4 deletions internal/user/repository/view/model/refresh_token.go
Expand Up @@ -24,14 +24,14 @@ const (
)

type RefreshTokenView struct {
ID string `json:"tokenId" gorm:"column:id"`
ID string `json:"tokenId" gorm:"column:id;primary_key"`
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
Token string `json:"-" gorm:"column:token"`
UserID string `json:"-" gorm:"column:user_id;primary_key"`
ClientID string `json:"clientID" gorm:"column:client_id;primary_key"`
UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id;primary_key"`
UserID string `json:"-" gorm:"column:user_id"`
ClientID string `json:"clientID" gorm:"column:client_id"`
UserAgentID string `json:"userAgentId" gorm:"column:user_agent_id"`
Audience pq.StringArray `json:"audience" gorm:"column:audience"`
Scopes pq.StringArray `json:"scopes" gorm:"column:scopes"`
AuthMethodsReferences pq.StringArray `json:"authMethodsReference" gorm:"column:amr"`
Expand Down
10 changes: 7 additions & 3 deletions internal/user/repository/view/refresh_token_view.go
@@ -1,13 +1,14 @@
package view

import (
"github.com/jinzhu/gorm"
"github.com/lib/pq"

"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/user/model"
usr_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/view/repository"
"github.com/jinzhu/gorm"
"github.com/lib/pq"
)

func RefreshTokenByID(db *gorm.DB, table, tokenID string) (*usr_model.RefreshTokenView, error) {
Expand Down Expand Up @@ -35,7 +36,10 @@ func RefreshTokensByUserID(db *gorm.DB, table, userID string) ([]*usr_model.Refr
}

func PutRefreshToken(db *gorm.DB, table string, token *usr_model.RefreshTokenView) error {
save := repository.PrepareSave(table)
save := repository.PrepareSaveOnConflict(table,
[]string{"client_id", "user_agent_id", "user_id"},
[]string{"id", "creation_date", "change_date", "token", "auth_time", "idle_expiration", "expiration", "sequence", "scopes", "audience", "amr"},
)
return save(db, token)
}

Expand Down
5 changes: 3 additions & 2 deletions internal/user/repository/view/token_view.go
@@ -1,13 +1,14 @@
package view

import (
"github.com/jinzhu/gorm"
"github.com/lib/pq"

"github.com/caos/zitadel/internal/domain"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/user/model"
usr_model "github.com/caos/zitadel/internal/user/repository/view/model"
"github.com/caos/zitadel/internal/view/repository"
"github.com/jinzhu/gorm"
"github.com/lib/pq"
)

func TokenByID(db *gorm.DB, table, tokenID string) (*usr_model.TokenView, error) {
Expand Down
16 changes: 16 additions & 0 deletions internal/view/repository/requests.go
Expand Up @@ -3,6 +3,7 @@ package repository
import (
"errors"
"fmt"
"strings"

"github.com/caos/logging"
"github.com/jinzhu/gorm"
Expand Down Expand Up @@ -80,6 +81,21 @@ func PrepareSave(table string) func(db *gorm.DB, object interface{}) error {
}
}

func PrepareSaveOnConflict(table string, conflictColumns, updateColumns []string) func(db *gorm.DB, object interface{}) error {
updates := make([]string, len(updateColumns))
for i, column := range updateColumns {
updates[i] = column + "=excluded." + column
}
onConflict := fmt.Sprintf("ON CONFLICT (%s) DO UPDATE SET %s", strings.Join(conflictColumns, ","), strings.Join(updates, ","))
return func(db *gorm.DB, object interface{}) error {
err := db.Table(table).Set("gorm:insert_option", onConflict).Save(object).Error
if err != nil {
return caos_errs.ThrowInternal(err, "VIEW-AfC7G", "unable to put object to view")
}
return nil
}
}

func PrepareDeleteByKey(table string, key ColumnKey, id interface{}) func(db *gorm.DB) error {
return func(db *gorm.DB) error {
err := db.Table(table).
Expand Down
2 changes: 2 additions & 0 deletions migrations/cockroach/V1.45__refresh_tokens.sql
@@ -0,0 +1,2 @@
ALTER TABLE auth.refresh_tokens ALTER COLUMN id SET NOT NULL;
ALTER TABLE auth.refresh_tokens ALTER PRIMARY KEY USING COLUMNS(id);