Files
threshold/internal/auth/oidc/service_token_request.go
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

98 lines
3.6 KiB
Go
Raw Normal View History

// Copyright (c) HashiCorp, Inc.
2021-04-08 20:54:32 -04:00
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2021-04-08 20:54:32 -04:00
package oidc
import (
"context"
"fmt"
2021-04-08 20:54:32 -04:00
"time"
"github.com/hashicorp/boundary/internal/auth/oidc/request"
"github.com/hashicorp/boundary/internal/authtoken"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/kms"
"google.golang.org/protobuf/proto"
)
// TokenRequest is an oidc domain service function for processing a token
// request from a Boundary client. Token requests are the result of a Boundary
// client polling the tokenUrl they received via StartAuth. On success, it
// returns Boundary token.
//
// * Decrypt the tokenRequestId. If encryption fails, it returns an error.
//
// * Use the authtoken.(Repository).IssueAuthToken to issue the request id's
// token and mark it as issued in the repo. If the token is already issue, an
// error is returned.
func TokenRequest(ctx context.Context, kms *kms.Kms, atRepoFn AuthTokenRepoFactory, authMethodId, tokenRequestId string) (*authtoken.AuthToken, error) {
2021-04-08 20:54:32 -04:00
const op = "oidc.TokenRequest"
if kms == nil {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing kms")
2021-04-08 20:54:32 -04:00
}
if atRepoFn == nil {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing auth token repo function")
2021-04-08 20:54:32 -04:00
}
if authMethodId == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing auth method id")
}
if tokenRequestId == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing token request id")
}
2021-04-08 20:54:32 -04:00
reqTkWrapper, err := UnwrapMessage(ctx, tokenRequestId)
2021-04-08 20:54:32 -04:00
if err != nil {
return nil, errors.Wrap(ctx, err, op)
2021-04-08 20:54:32 -04:00
}
if reqTkWrapper.ScopeId == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "request token id wrapper missing scope id")
2021-04-08 20:54:32 -04:00
}
if reqTkWrapper.AuthMethodId == "" {
return nil, errors.New(ctx, errors.InvalidParameter, op, "request token id wrapper missing auth method id")
2021-04-08 20:54:32 -04:00
}
if reqTkWrapper.AuthMethodId != authMethodId {
return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("%s auth method id does not match request wrapper auth method id: %s", authMethodId, reqTkWrapper.AuthMethodId))
}
2021-04-08 20:54:32 -04:00
// tokenRequestId is a proto request.Wrapper, which contains a cipher text field,
// so we need the derived wrapper that was used to encrypt it.
requestWrapper, err := requestWrappingWrapper(ctx, kms, reqTkWrapper.ScopeId, reqTkWrapper.AuthMethodId)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
2021-04-08 20:54:32 -04:00
}
reqTkBytes, err := decryptMessage(ctx, requestWrapper, reqTkWrapper)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
2021-04-08 20:54:32 -04:00
}
var reqTk request.Token
if err := proto.Unmarshal(reqTkBytes, &reqTk); err != nil {
return nil, errors.New(ctx, errors.Unknown, op, "unable to unmarshal request token", errors.WithWrap(err))
2021-04-08 20:54:32 -04:00
}
if reqTk.ExpirationTime == nil {
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing request token id expiration time")
2021-04-08 20:54:32 -04:00
}
// before proceeding, make sure the request hasn't timed out
if time.Now().After(reqTk.ExpirationTime.Timestamp.AsTime()) {
return nil, errors.New(ctx, errors.AuthAttemptExpired, op, "request token id has expired")
2021-04-08 20:54:32 -04:00
}
tokenRepo, err := atRepoFn()
if err != nil {
return nil, errors.Wrap(ctx, err, op)
2021-04-08 20:54:32 -04:00
}
authTk, err := tokenRepo.IssueAuthToken(ctx, reqTk.RequestId)
if err != nil {
if errors.Match(errors.T(errors.RecordNotFound), err) {
// We don't have it -- at least not yet. So don't mark it as an
// error, but nothing is returned.
return nil, nil
}
return nil, errors.Wrap(ctx, err, op)
2021-04-08 20:54:32 -04:00
}
if authTk.Token == "" {
return nil, errors.New(ctx, errors.Internal, op, "issued token is missing")
2021-04-08 20:54:32 -04:00
}
return authTk, nil
}