Rearrange some auth logic and add some opts useful for filtering/testing (#835)
This commit is contained in:
1 parent
ea878e49fa
commit
8b39faef1b
2 files changed
+310
-282
No files matched your search
+288
-271
@@ -195,277 +195,6 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
return
|
||||
}
|
||||
|
||||
// AdditionalVerification is used to perform checks of additional resources for
|
||||
// actions that need to touch more than one.
|
||||
func (r *VerifyResults) AdditionalVerification(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
v := r.v
|
||||
|
||||
ret.Error = handlers.ForbiddenError()
|
||||
|
||||
// Set other parameters the same to start with
|
||||
ret.Scope = r.Scope
|
||||
ret.UserId = r.UserId
|
||||
ret.AuthTokenId = r.AuthTokenId
|
||||
ret.v = r.v
|
||||
|
||||
opts := getOpts(opt...)
|
||||
|
||||
act := opts.withAction
|
||||
res := perms.Resource{
|
||||
ScopeId: opts.withScopeId,
|
||||
Id: opts.withId,
|
||||
Pin: opts.withPin,
|
||||
Type: opts.withType,
|
||||
}
|
||||
// Global scope has no parent ID; account for this
|
||||
if opts.withId == scope.Global.String() && opts.withType == resource.Scope {
|
||||
res.ScopeId = scope.Global.String()
|
||||
}
|
||||
|
||||
// Only perform lookup if it's actually different, otherwise use cached info
|
||||
if res.ScopeId != r.Scope.Id {
|
||||
iamRepo, err := v.iamRepoFn()
|
||||
if err != nil {
|
||||
v.logger.Error("additional verification: failed to get iam repo", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Look up scope details to return. We can skip a lookup when using the
|
||||
// global scope
|
||||
switch res.ScopeId {
|
||||
case "global":
|
||||
ret.Scope = &scopes.ScopeInfo{
|
||||
Id: scope.Global.String(),
|
||||
Type: scope.Global.String(),
|
||||
Name: scope.Global.String(),
|
||||
Description: "Global Scope",
|
||||
ParentScopeId: "",
|
||||
}
|
||||
|
||||
default:
|
||||
scp, err := iamRepo.LookupScope(v.ctx, v.res.ScopeId)
|
||||
if err != nil {
|
||||
v.logger.Error("additional verification: failed to get look up scope", "error", err)
|
||||
return
|
||||
}
|
||||
if scp == nil {
|
||||
v.logger.Error("additional verification: non-existent scope", "error", err)
|
||||
return
|
||||
}
|
||||
ret.Scope = &scopes.ScopeInfo{
|
||||
Id: scp.GetPublicId(),
|
||||
Type: scp.GetType(),
|
||||
Name: scp.GetName(),
|
||||
Description: scp.GetDescription(),
|
||||
ParentScopeId: scp.GetParentId(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Always allowed
|
||||
if v.requestInfo.TokenFormat == AuthTokenTypeRecoveryKms {
|
||||
ret.Error = nil
|
||||
return
|
||||
}
|
||||
|
||||
aclResults := v.acl.Allowed(res, act)
|
||||
|
||||
if !aclResults.Allowed {
|
||||
if v.requestInfo.DisableAuthzFailures {
|
||||
ret.Error = nil
|
||||
// TODO: Decide whether to remove this
|
||||
v.logger.Info("failed authz info for request", "resource", pretty.Sprint(v.res), "user_id", ret.UserId, "action", v.act.String())
|
||||
} else {
|
||||
// If the anon user was used (either no token, or invalid (perhaps
|
||||
// expired) token), return a 401. That way if it's an authn'd user
|
||||
// that is not authz'd we'll return 403 to be explicit.
|
||||
if ret.UserId == "u_anon" {
|
||||
ret.Error = handlers.UnauthenticatedError()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ret.Error = nil
|
||||
return
|
||||
}
|
||||
|
||||
func (v verifier) performAuthCheck() (aclResults perms.ACLResults, userId string, scopeInfo *scopes.ScopeInfo, retAcl perms.ACL, retErr error) {
|
||||
// Ensure we return an error by default if we forget to set this somewhere
|
||||
retErr = errors.New("unknown")
|
||||
// Make the linter happy
|
||||
_ = retErr
|
||||
scopeInfo = new(scopes.ScopeInfo)
|
||||
userId = "u_anon"
|
||||
var accountId string
|
||||
|
||||
// Validate the token and fetch the corresponding user ID
|
||||
switch v.requestInfo.TokenFormat {
|
||||
case AuthTokenTypeUnknown:
|
||||
// Nothing; remain as the anonymous user
|
||||
|
||||
case AuthTokenTypeRecoveryKms:
|
||||
// We validated the encrypted token in decryptToken and handled the
|
||||
// nonces there, so just set the user
|
||||
userId = "u_recovery"
|
||||
|
||||
case AuthTokenTypeBearer, AuthTokenTypeSplitCookie:
|
||||
if v.requestInfo.Token == "" {
|
||||
// This will end up staying as the anonymous user
|
||||
break
|
||||
}
|
||||
tokenRepo, err := v.authTokenRepoFn()
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to get authtoken repo: %w", err)
|
||||
return
|
||||
}
|
||||
at, err := tokenRepo.ValidateToken(v.ctx, v.requestInfo.PublicId, v.requestInfo.Token)
|
||||
if err != nil {
|
||||
// Continue as the anonymous user as maybe this token is expired but
|
||||
// we can still perform the action
|
||||
v.logger.Error("perform auth check: error validating token; continuing as anonymous user", "error", err)
|
||||
break
|
||||
}
|
||||
if at != nil {
|
||||
accountId = at.GetAuthAccountId()
|
||||
userId = at.GetIamUserId()
|
||||
if userId == "" {
|
||||
v.logger.Warn("perform auth check: valid token did not map to a user, likely because no account is associated with the user any longer; continuing as u_anon", "token_id", at.GetPublicId())
|
||||
userId = "u_anon"
|
||||
accountId = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iamRepo, err := v.iamRepoFn()
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to get iam repo: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Look up scope details to return. We can skip a lookup when using the
|
||||
// global scope
|
||||
switch v.res.ScopeId {
|
||||
case "global":
|
||||
scopeInfo = &scopes.ScopeInfo{
|
||||
Id: scope.Global.String(),
|
||||
Type: scope.Global.String(),
|
||||
Name: scope.Global.String(),
|
||||
Description: "Global Scope",
|
||||
ParentScopeId: "",
|
||||
}
|
||||
|
||||
default:
|
||||
scp, err := iamRepo.LookupScope(v.ctx, v.res.ScopeId)
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to lookup scope: %w", err)
|
||||
return
|
||||
}
|
||||
if scp == nil {
|
||||
retErr = fmt.Errorf("perform auth check: non-existent scope %q", v.res.ScopeId)
|
||||
return
|
||||
}
|
||||
scopeInfo = &scopes.ScopeInfo{
|
||||
Id: scp.GetPublicId(),
|
||||
Type: scp.GetType(),
|
||||
Name: scp.GetName(),
|
||||
Description: scp.GetDescription(),
|
||||
ParentScopeId: scp.GetParentId(),
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we don't need to look up grants since it's automatically allowed
|
||||
if v.requestInfo.TokenFormat == AuthTokenTypeRecoveryKms {
|
||||
aclResults.Allowed = true
|
||||
retErr = nil
|
||||
return
|
||||
}
|
||||
|
||||
var parsedGrants []perms.Grant
|
||||
var grantPairs []perms.GrantPair
|
||||
|
||||
// Fetch and parse grants for this user ID (which may include grants for
|
||||
// u_anon and u_auth)
|
||||
grantPairs, err = iamRepo.GrantsForUser(v.ctx, userId)
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to query for user grants: %w", err)
|
||||
return
|
||||
}
|
||||
parsedGrants = make([]perms.Grant, 0, len(grantPairs))
|
||||
for _, pair := range grantPairs {
|
||||
parsed, err := perms.Parse(
|
||||
pair.ScopeId,
|
||||
pair.Grant,
|
||||
perms.WithUserId(userId),
|
||||
perms.WithAccountId(accountId),
|
||||
perms.WithSkipFinalValidation(true))
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to parse grant %#v: %w", pair.Grant, err)
|
||||
return
|
||||
}
|
||||
parsedGrants = append(parsedGrants, parsed)
|
||||
}
|
||||
|
||||
retAcl = perms.NewACL(parsedGrants...)
|
||||
aclResults = retAcl.Allowed(*v.res, v.act)
|
||||
retErr = nil
|
||||
return
|
||||
}
|
||||
|
||||
// GetTokenFromRequest pulls the token from either the Authorization header or
|
||||
// split cookies and parses it. If it cannot be parsed successfully, the issue
|
||||
// is logged and we return blank, so logic will continue as the anonymous user.
|
||||
// The public ID and _encrypted_ token are returned along with the token format.
|
||||
func GetTokenFromRequest(logger hclog.Logger, kmsCache *kms.Kms, req *http.Request) (string, string, TokenFormat) {
|
||||
// First, get the token, either from the authorization header or from split
|
||||
// cookies
|
||||
var receivedTokenType TokenFormat
|
||||
var fullToken string
|
||||
if authHeader := req.Header.Get("Authorization"); authHeader != "" {
|
||||
headerSplit := strings.SplitN(strings.TrimSpace(authHeader), " ", 2)
|
||||
if len(headerSplit) == 2 && strings.EqualFold(strings.TrimSpace(headerSplit[0]), "bearer") {
|
||||
receivedTokenType = AuthTokenTypeBearer
|
||||
fullToken = strings.TrimSpace(headerSplit[1])
|
||||
}
|
||||
}
|
||||
if receivedTokenType != AuthTokenTypeBearer {
|
||||
var httpCookiePayload string
|
||||
var jsCookiePayload string
|
||||
if hc, err := req.Cookie(handlers.HttpOnlyCookieName); err == nil {
|
||||
httpCookiePayload = hc.Value
|
||||
}
|
||||
if jc, err := req.Cookie(handlers.JsVisibleCookieName); err == nil {
|
||||
jsCookiePayload = jc.Value
|
||||
}
|
||||
if httpCookiePayload != "" && jsCookiePayload != "" {
|
||||
receivedTokenType = AuthTokenTypeSplitCookie
|
||||
fullToken = jsCookiePayload + httpCookiePayload
|
||||
}
|
||||
}
|
||||
|
||||
if receivedTokenType == AuthTokenTypeUnknown || fullToken == "" {
|
||||
// We didn't find auth info or a client screwed up and put in a blank
|
||||
// header instead of nothing at all, so return blank which will indicate
|
||||
// the anonymouse user
|
||||
return "", "", AuthTokenTypeUnknown
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fullToken, "r_") {
|
||||
return "", fullToken, AuthTokenTypeRecoveryKms
|
||||
}
|
||||
|
||||
splitFullToken := strings.Split(fullToken, "_")
|
||||
if len(splitFullToken) != 3 {
|
||||
logger.Trace("get token from request: unexpected number of segments in token; continuing as anonymous user", "expected", 3, "found", len(splitFullToken))
|
||||
return "", "", AuthTokenTypeUnknown
|
||||
}
|
||||
|
||||
publicId := strings.Join(splitFullToken[0:2], "_")
|
||||
encryptedToken := splitFullToken[2]
|
||||
|
||||
return publicId, encryptedToken, receivedTokenType
|
||||
}
|
||||
|
||||
func (v *verifier) decryptToken() {
|
||||
switch v.requestInfo.TokenFormat {
|
||||
case AuthTokenTypeUnknown:
|
||||
@@ -590,3 +319,291 @@ func (v *verifier) decryptToken() {
|
||||
v.logger.Warn("recovery KMS was used to authorize a call", "url", v.requestInfo.Path, "method", v.requestInfo.Method)
|
||||
}
|
||||
}
|
||||
|
||||
func (v verifier) performAuthCheck() (aclResults perms.ACLResults, userId string, scopeInfo *scopes.ScopeInfo, retAcl perms.ACL, retErr error) {
|
||||
// Ensure we return an error by default if we forget to set this somewhere
|
||||
retErr = errors.New("unknown")
|
||||
// Make the linter happy
|
||||
_ = retErr
|
||||
scopeInfo = new(scopes.ScopeInfo)
|
||||
userId = "u_anon"
|
||||
var accountId string
|
||||
|
||||
// Validate the token and fetch the corresponding user ID
|
||||
switch v.requestInfo.TokenFormat {
|
||||
case AuthTokenTypeUnknown:
|
||||
// Nothing; remain as the anonymous user
|
||||
|
||||
case AuthTokenTypeRecoveryKms:
|
||||
// We validated the encrypted token in decryptToken and handled the
|
||||
// nonces there, so just set the user
|
||||
userId = "u_recovery"
|
||||
|
||||
case AuthTokenTypeBearer, AuthTokenTypeSplitCookie:
|
||||
if v.requestInfo.Token == "" {
|
||||
// This will end up staying as the anonymous user
|
||||
break
|
||||
}
|
||||
tokenRepo, err := v.authTokenRepoFn()
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to get authtoken repo: %w", err)
|
||||
return
|
||||
}
|
||||
at, err := tokenRepo.ValidateToken(v.ctx, v.requestInfo.PublicId, v.requestInfo.Token)
|
||||
if err != nil {
|
||||
// Continue as the anonymous user as maybe this token is expired but
|
||||
// we can still perform the action
|
||||
v.logger.Error("perform auth check: error validating token; continuing as anonymous user", "error", err)
|
||||
break
|
||||
}
|
||||
if at != nil {
|
||||
accountId = at.GetAuthAccountId()
|
||||
userId = at.GetIamUserId()
|
||||
if userId == "" {
|
||||
v.logger.Warn("perform auth check: valid token did not map to a user, likely because no account is associated with the user any longer; continuing as u_anon", "token_id", at.GetPublicId())
|
||||
userId = "u_anon"
|
||||
accountId = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iamRepo, err := v.iamRepoFn()
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to get iam repo: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Look up scope details to return. We can skip a lookup when using the
|
||||
// global scope
|
||||
switch v.res.ScopeId {
|
||||
case "global":
|
||||
scopeInfo = &scopes.ScopeInfo{
|
||||
Id: scope.Global.String(),
|
||||
Type: scope.Global.String(),
|
||||
Name: scope.Global.String(),
|
||||
Description: "Global Scope",
|
||||
ParentScopeId: "",
|
||||
}
|
||||
|
||||
default:
|
||||
scp, err := iamRepo.LookupScope(v.ctx, v.res.ScopeId)
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to lookup scope: %w", err)
|
||||
return
|
||||
}
|
||||
if scp == nil {
|
||||
retErr = fmt.Errorf("perform auth check: non-existent scope %q", v.res.ScopeId)
|
||||
return
|
||||
}
|
||||
scopeInfo = &scopes.ScopeInfo{
|
||||
Id: scp.GetPublicId(),
|
||||
Type: scp.GetType(),
|
||||
Name: scp.GetName(),
|
||||
Description: scp.GetDescription(),
|
||||
ParentScopeId: scp.GetParentId(),
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we don't need to look up grants since it's automatically allowed
|
||||
if v.requestInfo.TokenFormat == AuthTokenTypeRecoveryKms {
|
||||
aclResults.Allowed = true
|
||||
retErr = nil
|
||||
return
|
||||
}
|
||||
|
||||
var parsedGrants []perms.Grant
|
||||
var grantPairs []perms.GrantPair
|
||||
|
||||
// Fetch and parse grants for this user ID (which may include grants for
|
||||
// u_anon and u_auth)
|
||||
grantPairs, err = iamRepo.GrantsForUser(v.ctx, userId)
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to query for user grants: %w", err)
|
||||
return
|
||||
}
|
||||
parsedGrants = make([]perms.Grant, 0, len(grantPairs))
|
||||
for _, pair := range grantPairs {
|
||||
parsed, err := perms.Parse(
|
||||
pair.ScopeId,
|
||||
pair.Grant,
|
||||
perms.WithUserId(userId),
|
||||
perms.WithAccountId(accountId),
|
||||
perms.WithSkipFinalValidation(true))
|
||||
if err != nil {
|
||||
retErr = fmt.Errorf("perform auth check: failed to parse grant %#v: %w", pair.Grant, err)
|
||||
return
|
||||
}
|
||||
parsedGrants = append(parsedGrants, parsed)
|
||||
}
|
||||
|
||||
retAcl = perms.NewACL(parsedGrants...)
|
||||
aclResults = retAcl.Allowed(*v.res, v.act)
|
||||
retErr = nil
|
||||
return
|
||||
}
|
||||
|
||||
// AdditionalVerification is used to perform checks of additional resources for
|
||||
// actions that need to touch more than one.
|
||||
func (r *VerifyResults) AdditionalVerification(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
v := r.v
|
||||
|
||||
ret.Error = handlers.ForbiddenError()
|
||||
|
||||
// Set other parameters the same to start with
|
||||
ret.Scope = r.Scope
|
||||
ret.UserId = r.UserId
|
||||
ret.AuthTokenId = r.AuthTokenId
|
||||
ret.v = r.v
|
||||
|
||||
opts := getOpts(opt...)
|
||||
|
||||
act := opts.withAction
|
||||
res := perms.Resource{
|
||||
ScopeId: opts.withScopeId,
|
||||
Id: opts.withId,
|
||||
Pin: opts.withPin,
|
||||
Type: opts.withType,
|
||||
}
|
||||
// Global scope has no parent ID; account for this
|
||||
if opts.withId == scope.Global.String() && opts.withType == resource.Scope {
|
||||
res.ScopeId = scope.Global.String()
|
||||
}
|
||||
|
||||
// Only perform lookup if it's actually different, otherwise use cached info
|
||||
if res.ScopeId != r.Scope.Id {
|
||||
iamRepo, err := v.iamRepoFn()
|
||||
if err != nil {
|
||||
v.logger.Error("additional verification: failed to get iam repo", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Look up scope details to return. We can skip a lookup when using the
|
||||
// global scope
|
||||
switch res.ScopeId {
|
||||
case "global":
|
||||
ret.Scope = &scopes.ScopeInfo{
|
||||
Id: scope.Global.String(),
|
||||
Type: scope.Global.String(),
|
||||
Name: scope.Global.String(),
|
||||
Description: "Global Scope",
|
||||
ParentScopeId: "",
|
||||
}
|
||||
|
||||
default:
|
||||
scp, err := iamRepo.LookupScope(v.ctx, v.res.ScopeId)
|
||||
if err != nil {
|
||||
v.logger.Error("additional verification: failed to get look up scope", "error", err)
|
||||
return
|
||||
}
|
||||
if scp == nil {
|
||||
v.logger.Error("additional verification: non-existent scope", "error", err)
|
||||
return
|
||||
}
|
||||
ret.Scope = &scopes.ScopeInfo{
|
||||
Id: scp.GetPublicId(),
|
||||
Type: scp.GetType(),
|
||||
Name: scp.GetName(),
|
||||
Description: scp.GetDescription(),
|
||||
ParentScopeId: scp.GetParentId(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: the exclusions for recovery/anonymous user below are best effort.
|
||||
// It's up to the caller to ensure that an invalid user ID for the operation
|
||||
// is not actually allowed. The options here are really for
|
||||
// listing/filtering purposes.
|
||||
|
||||
// Always allowed
|
||||
if v.requestInfo.TokenFormat == AuthTokenTypeRecoveryKms {
|
||||
if opts.withRecoveryTokenNotAllowed {
|
||||
// Don't allow it. This is used in some cases like target listing
|
||||
// where the command will succeed for most things but it's not
|
||||
// allowed for an authorize-session action.
|
||||
return
|
||||
}
|
||||
ret.Error = nil
|
||||
return
|
||||
}
|
||||
|
||||
if opts.withAnonymousUserNotAllowed {
|
||||
// Similar to above, in some cases we never allow the anonymous user,
|
||||
// such as with targets and authorize-session
|
||||
return
|
||||
}
|
||||
|
||||
aclResults := v.acl.Allowed(res, act)
|
||||
|
||||
if !aclResults.Allowed {
|
||||
if v.requestInfo.DisableAuthzFailures {
|
||||
ret.Error = nil
|
||||
// TODO: Decide whether to remove this
|
||||
v.logger.Info("failed authz info for request", "resource", pretty.Sprint(v.res), "user_id", ret.UserId, "action", v.act.String())
|
||||
} else {
|
||||
// If the anon user was used (either no token, or invalid (perhaps
|
||||
// expired) token), return a 401. That way if it's an authn'd user
|
||||
// that is not authz'd we'll return 403 to be explicit.
|
||||
if ret.UserId == "u_anon" {
|
||||
ret.Error = handlers.UnauthenticatedError()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ret.Error = nil
|
||||
return
|
||||
}
|
||||
|
||||
// GetTokenFromRequest pulls the token from either the Authorization header or
|
||||
// split cookies and parses it. If it cannot be parsed successfully, the issue
|
||||
// is logged and we return blank, so logic will continue as the anonymous user.
|
||||
// The public ID and _encrypted_ token are returned along with the token format.
|
||||
func GetTokenFromRequest(logger hclog.Logger, kmsCache *kms.Kms, req *http.Request) (string, string, TokenFormat) {
|
||||
// First, get the token, either from the authorization header or from split
|
||||
// cookies
|
||||
var receivedTokenType TokenFormat
|
||||
var fullToken string
|
||||
if authHeader := req.Header.Get("Authorization"); authHeader != "" {
|
||||
headerSplit := strings.SplitN(strings.TrimSpace(authHeader), " ", 2)
|
||||
if len(headerSplit) == 2 && strings.EqualFold(strings.TrimSpace(headerSplit[0]), "bearer") {
|
||||
receivedTokenType = AuthTokenTypeBearer
|
||||
fullToken = strings.TrimSpace(headerSplit[1])
|
||||
}
|
||||
}
|
||||
if receivedTokenType != AuthTokenTypeBearer {
|
||||
var httpCookiePayload string
|
||||
var jsCookiePayload string
|
||||
if hc, err := req.Cookie(handlers.HttpOnlyCookieName); err == nil {
|
||||
httpCookiePayload = hc.Value
|
||||
}
|
||||
if jc, err := req.Cookie(handlers.JsVisibleCookieName); err == nil {
|
||||
jsCookiePayload = jc.Value
|
||||
}
|
||||
if httpCookiePayload != "" && jsCookiePayload != "" {
|
||||
receivedTokenType = AuthTokenTypeSplitCookie
|
||||
fullToken = jsCookiePayload + httpCookiePayload
|
||||
}
|
||||
}
|
||||
|
||||
if receivedTokenType == AuthTokenTypeUnknown || fullToken == "" {
|
||||
// We didn't find auth info or a client screwed up and put in a blank
|
||||
// header instead of nothing at all, so return blank which will indicate
|
||||
// the anonymouse user
|
||||
return "", "", AuthTokenTypeUnknown
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fullToken, "r_") {
|
||||
return "", fullToken, AuthTokenTypeRecoveryKms
|
||||
}
|
||||
|
||||
splitFullToken := strings.Split(fullToken, "_")
|
||||
if len(splitFullToken) != 3 {
|
||||
logger.Trace("get token from request: unexpected number of segments in token; continuing as anonymous user", "expected", 3, "found", len(splitFullToken))
|
||||
return "", "", AuthTokenTypeUnknown
|
||||
}
|
||||
|
||||
publicId := strings.Join(splitFullToken[0:2], "_")
|
||||
encryptedToken := splitFullToken[2]
|
||||
|
||||
return publicId, encryptedToken, receivedTokenType
|
||||
}
|
||||
+22
-11
@@ -19,20 +19,19 @@ type Option func(*options)
|
||||
|
||||
// options = how options are represented
|
||||
type options struct {
|
||||
withScopeId string
|
||||
withPin string
|
||||
withId string
|
||||
withAction action.Type
|
||||
withType resource.Type
|
||||
withUserId string
|
||||
withKms *kms.Kms
|
||||
withScopeId string
|
||||
withPin string
|
||||
withId string
|
||||
withAction action.Type
|
||||
withType resource.Type
|
||||
withUserId string
|
||||
withKms *kms.Kms
|
||||
withRecoveryTokenNotAllowed bool
|
||||
withAnonymousUserNotAllowed bool
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
return options{
|
||||
withScopeId: "",
|
||||
withUserId: "",
|
||||
}
|
||||
return options{}
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
@@ -76,3 +75,15 @@ func WithKms(kms *kms.Kms) Option {
|
||||
o.withKms = kms
|
||||
}
|
||||
}
|
||||
|
||||
func WithRecoveryTokenNotAllowed(notAllowed bool) Option {
|
||||
return func(o *options) {
|
||||
o.withRecoveryTokenNotAllowed = notAllowed
|
||||
}
|
||||
}
|
||||
|
||||
func WithAnonymousUserNotAllowed(notAllowed bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAnonymousUserNotAllowed = notAllowed
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user