2021-07-29 18:52:56 -06:00
// Copyright (c) HashiCorp, Inc.
2021-04-13 09:21:26 -07:00
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2021-04-08 20:54:32 -04:00
package authmethods
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strings"
"github.com/hashicorp/boundary/internal/auth/oidc"
oidcstore "github.com/hashicorp/boundary/internal/auth/oidc/store"
2022-05-09 12:45:10 -07:00
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
2021-04-08 20:54:32 -04:00
"github.com/hashicorp/boundary/internal/errors"
2023-09-12 08:15:34 -04:00
"github.com/hashicorp/boundary/internal/event"
2021-04-08 20:54:32 -04:00
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
"github.com/hashicorp/boundary/internal/types/action"
2021-08-26 10:44:41 -04:00
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/authmethods"
2021-04-08 20:54:32 -04:00
"google.golang.org/grpc/codes"
)
const (
// commands
startCommand = "start"
callbackCommand = "callback"
tokenCommand = "token"
// token request/response fields
2021-04-12 13:57:14 -05:00
statusField = "status"
2021-04-08 20:54:32 -04:00
// field names
issuerField = "attributes.issuer"
clientSecretField = "attributes.client_secret"
clientIdField = "attributes.client_id"
clientSecretHmacField = "attributes.client_secret_hmac"
stateField = "attributes.state"
callbackUrlField = "attributes.callback_url"
apiUrlPrefixField = "attributes.api_url_prefix"
2021-06-02 07:39:45 -07:00
idpCaCertsField = "attributes.idp_ca_certs"
2021-04-08 20:54:32 -04:00
signingAlgorithmField = "attributes.signing_algorithms"
disableDiscoveredConfigValidationField = "attributes.disable_discovered_config_validation"
roundtripPayloadAttributesField = "attributes.roundtrip_payload"
codeField = "attributes.code"
2021-04-28 06:53:13 -04:00
claimsScopesField = "attributes.claims_scopes"
2021-05-04 08:41:04 -04:00
accountClaimMapsField = "attributes.account_claim_maps"
2023-11-21 11:30:02 -05:00
promptsField = "attributes.prompts"
2021-04-08 20:54:32 -04:00
)
var oidcMaskManager handlers . MaskManager
func init () {
var err error
2023-06-06 17:09:08 -04:00
if oidcMaskManager , err = handlers . NewMaskManager ( context . Background (), handlers . MaskDestination { & oidcstore . AuthMethod {}}, handlers . MaskSource { & pb . AuthMethod {}, & pb . OidcAuthMethodAttributes {}}); err != nil {
2021-04-08 20:54:32 -04:00
panic ( err )
}
2023-10-31 13:44:17 +00:00
IdActions [ oidc . Subtype ] = action . NewActionSet (
2021-04-23 09:13:37 -05:00
action . NoOp ,
2021-04-08 20:54:32 -04:00
action . Read ,
action . Update ,
action . Delete ,
action . ChangeState ,
action . Authenticate ,
2023-10-31 13:44:17 +00:00
)
2021-04-08 20:54:32 -04:00
}
type oidcState uint
const (
2021-04-13 18:07:50 -05:00
_ oidcState = iota
2021-04-08 20:54:32 -04:00
inactiveState
privateState
publicState
)
var oidcStateMap = map [ string ] oidcState {
inactiveState . String (): inactiveState ,
privateState . String (): privateState ,
publicState . String (): publicState ,
}
func ( o oidcState ) String () string {
return [ ... ] string {
"unknown" ,
"inactive" ,
"active-private" ,
"active-public" ,
}[ o ]
}
// createOidcInRepo creates an oidc auth method in a repo and returns the result.
// This method should never return a nil AuthMethod without returning an error.
func ( s Service ) createOidcInRepo ( ctx context . Context , scopeId string , item * pb . AuthMethod ) ( * oidc . AuthMethod , error ) {
2021-07-29 18:52:56 -06:00
u , _ , _ , err := toStorageOidcAuthMethod ( ctx , scopeId , item )
2021-04-08 20:54:32 -04:00
if err != nil {
return nil , err
}
repo , err := s . oidcRepoFn ()
if err != nil {
return nil , err
}
out , err := repo . CreateAuthMethod ( ctx , u )
if err != nil {
return nil , fmt . Errorf ( "unable to create auth method: %w" , err )
}
return out , nil
}
func ( s Service ) updateOidcInRepo ( ctx context . Context , scopeId string , req * pbs . UpdateAuthMethodRequest ) ( * oidc . AuthMethod , bool , error ) {
item := req . GetItem ()
2021-07-29 18:52:56 -06:00
u , dryRun , forced , err := toStorageOidcAuthMethod ( ctx , scopeId , item )
2021-04-08 20:54:32 -04:00
if err != nil {
return nil , dryRun , err
}
u . PublicId = req . GetId ()
var opts [] oidc . Option
if forced {
opts = append ( opts , oidc . WithForce ())
}
if dryRun {
opts = append ( opts , oidc . WithDryRun ())
}
version := item . GetVersion ()
dbMask := oidcMaskManager . Translate ( req . GetUpdateMask (). GetPaths ())
if len ( dbMask ) == 0 {
return nil , dryRun , handlers . InvalidArgumentErrorf ( "No valid fields included in the update mask." , map [ string ] string { "update_mask" : "No valid fields provided in the update mask." })
}
repo , err := s . oidcRepoFn ()
if err != nil {
return nil , dryRun , err
}
out , rowsUpdated , err := repo . UpdateAuthMethod ( ctx , u , version , dbMask , opts ... )
if err != nil {
return nil , dryRun , fmt . Errorf ( "unable to update auth method: %w" , err )
}
if rowsUpdated == 0 && ! dryRun && out == nil {
return nil , dryRun , handlers . NotFoundErrorf ( "AuthMethod %q doesn't exist or incorrect version provided." , req . GetId ())
}
return out , dryRun , nil
}
func ( s Service ) authenticateOidc ( ctx context . Context , req * pbs . AuthenticateRequest , authResults * auth . VerifyResults ) ( * pbs . AuthenticateResponse , error ) {
const op = "authmethod_service.(Service).authenticateOidc"
if req == nil {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . InvalidParameter , op , "Nil request." )
2021-04-08 20:54:32 -04:00
}
if authResults == nil {
2021-07-29 18:52:56 -06:00
return nil , errors . New ( ctx , errors . InvalidParameter , op , "Nil auth results." )
2021-04-08 20:54:32 -04:00
}
switch req . GetCommand () {
case startCommand :
2021-04-13 09:21:26 -07:00
return s . authenticateOidcStart ( ctx , req )
2021-04-08 20:54:32 -04:00
case callbackCommand :
2021-04-13 09:21:26 -07:00
return s . authenticateOidcCallback ( ctx , req )
2021-04-08 20:54:32 -04:00
case tokenCommand :
return s . authenticateOidcToken ( ctx , req , authResults )
}
2022-04-11 14:50:29 -04:00
return & pbs . AuthenticateResponse { Command : req . GetCommand ()}, nil
2021-04-08 20:54:32 -04:00
}
2021-04-13 09:21:26 -07:00
func ( s Service ) authenticateOidcStart ( ctx context . Context , req * pbs . AuthenticateRequest ) ( * pbs . AuthenticateResponse , error ) {
2021-04-08 20:54:32 -04:00
const op = "authmethod_service.(Service).authenticateOidcStart"
if req == nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . InvalidArgumentErrorf ( "Nil request." , nil )
2021-04-08 20:54:32 -04:00
}
var opts [] oidc . Option
2022-04-11 14:50:29 -04:00
attrs := req . GetOidcStartAttributes ()
2021-04-13 09:21:26 -07:00
if attrs . GetCachedRoundtripPayload () != "" {
opts = append ( opts , oidc . WithRoundtripPayload ( attrs . GetCachedRoundtripPayload ()))
2021-04-08 20:54:32 -04:00
}
2021-04-13 09:21:26 -07:00
authUrl , tokenId , err := oidc . StartAuth ( ctx , s . oidcRepoFn , req . GetAuthMethodId (), opts ... )
2024-08-30 16:33:18 +01:00
switch {
case errors . Match ( errors . T ( errors . AuthMethodInactive ), err ):
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . FailedPrecondition , "Cannot start authentication against an inactive OIDC auth method" )
case errors . Match ( errors . T ( errors . RecordNotFound ), err ):
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . NotFound , "Auth method %s was not found" , req . GetAuthMethodId ())
case errors . Match ( errors . T ( errors . InvalidParameter ), err ):
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . InvalidArgument , err . Error ())
case err != nil :
2021-07-28 06:31:16 -04:00
event . WriteError ( ctx , op , err , event . WithInfoMsg ( "error starting the oidc authentication flow" ))
2024-06-06 15:59:43 +02:00
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Error generating parameters for starting the OIDC flow. See the controller's log for more information." )
2021-04-08 20:54:32 -04:00
}
2022-04-11 14:50:29 -04:00
return & pbs . AuthenticateResponse {
Command : req . GetCommand (),
Attrs : & pbs . AuthenticateResponse_OidcAuthMethodAuthenticateStartResponse {
OidcAuthMethodAuthenticateStartResponse : & pb . OidcAuthMethodAuthenticateStartResponse {
AuthUrl : authUrl . String (),
TokenId : tokenId ,
},
},
}, nil
2021-04-08 20:54:32 -04:00
}
2021-04-13 09:21:26 -07:00
// authenticateOidcCallback behaves differently than other service methods.
// Because of the way it this is called by the end user, it should only return
// an error if we are unable to lookup the auth method or the request
// parameters were invalid. All other errors should be returned back through
// the response as a finalRedirectUrl to an endpoint that can properly show the
// error details.
func ( s Service ) authenticateOidcCallback ( ctx context . Context , req * pbs . AuthenticateRequest ) ( * pbs . AuthenticateResponse , error ) {
2021-04-08 20:54:32 -04:00
const op = "authmethod_service.(Service).authenticateOidcCallback"
2021-04-29 14:47:13 -07:00
// TODO: Return all errors (including the validate request based errors
// in the redirect URL once we start looking at the url used for this
// request instead of requiring the API URL to be set on the auth method.
2021-04-08 20:54:32 -04:00
if req == nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . InvalidArgumentErrorf ( "Nil request." , nil )
2021-04-08 20:54:32 -04:00
}
2021-04-13 09:21:26 -07:00
repo , err := s . oidcRepoFn ()
if err != nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , err . Error ())
2021-04-13 09:21:26 -07:00
}
am , err := repo . LookupAuthMethod ( ctx , req . GetAuthMethodId ())
if err != nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , err . Error ())
2021-04-13 09:21:26 -07:00
}
if am == nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . NotFoundErrorf ( "Auth method %s not found." , req . GetAuthMethodId ())
2021-04-13 09:21:26 -07:00
}
if am . GetApiUrl () == "" {
2024-06-06 15:59:43 +02:00
return nil , handlers . InvalidArgumentErrorf ( "Auth method doesn't have API URL defined." , nil )
2021-04-13 09:21:26 -07:00
}
errRedirectBase := fmt . Sprintf ( oidc . AuthenticationErrorsEndpoint , am . GetApiUrl ())
2021-04-29 14:47:13 -07:00
errResponse := func ( err error ) ( * pbs . AuthenticateResponse , error ) {
2021-04-13 09:21:26 -07:00
u := make ( url . Values )
2021-04-29 14:47:13 -07:00
pbErr := handlers . ToApiError ( err )
out , err := handlers . JSONMarshaler (). Marshal ( pbErr )
if err != nil {
2024-06-06 15:59:43 +02:00
event . WriteError ( ctx , op , err , event . WithInfoMsg ( "unable to marshal the error for callback" ))
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "unable to marshal the error for callback" )
2021-04-29 14:47:13 -07:00
}
u . Add ( "error" , string ( out ))
2021-04-13 09:21:26 -07:00
errRedirect := fmt . Sprintf ( "%s?%s" , errRedirectBase , u . Encode ())
2022-04-11 14:50:29 -04:00
return & pbs . AuthenticateResponse {
Command : callbackCommand ,
Attrs : & pbs . AuthenticateResponse_OidcAuthMethodAuthenticateCallbackResponse {
OidcAuthMethodAuthenticateCallbackResponse : & pb . OidcAuthMethodAuthenticateCallbackResponse {
FinalRedirectUrl : errRedirect ,
},
},
}, nil
2021-04-08 20:54:32 -04:00
}
2022-04-11 14:50:29 -04:00
attrs := req . GetOidcAuthMethodAuthenticateCallbackRequest ()
2021-04-08 20:54:32 -04:00
2021-04-13 09:21:26 -07:00
var finalRedirectUrl string
if attrs . GetError () != "" {
2021-07-29 18:52:56 -06:00
err := errors . Wrap ( ctx , fmt . Errorf ( "Error: %q, Details: %q" , attrs . GetError (), attrs . GetErrorDescription ()), op , errors . WithCode ( errors . OidcProviderCallbackError ))
2021-04-29 14:47:13 -07:00
return errResponse ( err )
2021-04-13 09:21:26 -07:00
}
finalRedirectUrl , err = oidc . Callback (
2021-04-08 20:54:32 -04:00
ctx ,
s . oidcRepoFn ,
oidc . IamRepoFactory ( s . iamRepoFn ),
s . atRepoFn ,
2021-04-13 09:21:26 -07:00
am ,
2021-04-08 20:54:32 -04:00
attrs . GetState (),
attrs . GetCode ())
if err != nil {
2021-07-29 18:52:56 -06:00
return errResponse ( errors . New ( ctx , errors . InvalidParameter , op , "Callback validation failed." , errors . WithWrap ( err )))
2021-04-08 20:54:32 -04:00
}
2022-04-11 14:50:29 -04:00
return & pbs . AuthenticateResponse {
Command : req . GetCommand (),
Attrs : & pbs . AuthenticateResponse_OidcAuthMethodAuthenticateCallbackResponse {
OidcAuthMethodAuthenticateCallbackResponse : & pb . OidcAuthMethodAuthenticateCallbackResponse {
FinalRedirectUrl : finalRedirectUrl ,
},
},
}, nil
2021-04-08 20:54:32 -04:00
}
func ( s Service ) authenticateOidcToken ( ctx context . Context , req * pbs . AuthenticateRequest , authResults * auth . VerifyResults ) ( * pbs . AuthenticateResponse , error ) {
const op = "authmethod_service.(Service).authenticateOidcToken"
if req == nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . InvalidArgumentErrorf ( "Nil request." , nil )
2021-04-08 20:54:32 -04:00
}
if authResults == nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . InvalidArgumentErrorf ( "Nil auth results." , nil )
2021-04-08 20:54:32 -04:00
}
2022-04-11 14:50:29 -04:00
if req . GetOidcAuthMethodAuthenticateTokenRequest () == nil {
2024-06-06 15:59:43 +02:00
return nil , handlers . InvalidArgumentErrorf ( "Nil request attributes." , nil )
2021-04-08 20:54:32 -04:00
}
2022-04-11 14:50:29 -04:00
attrs := req . GetOidcAuthMethodAuthenticateTokenRequest ()
2021-04-08 20:54:32 -04:00
if attrs . TokenId == "" {
2024-06-06 15:59:43 +02:00
return nil , handlers . InvalidArgumentErrorf ( "Empty token ID in request attributes." , nil )
2021-04-08 20:54:32 -04:00
}
2021-04-12 17:17:28 -04:00
token , err := oidc . TokenRequest ( ctx , s . kms , s . atRepoFn , req . GetAuthMethodId (), attrs . TokenId )
2021-04-08 20:54:32 -04:00
if err != nil {
switch {
case errors . Match ( errors . T ( errors . Forbidden ), err ):
2024-06-06 15:59:43 +02:00
return nil , handlers . ForbiddenError ()
2021-04-08 20:54:32 -04:00
case errors . Match ( errors . T ( errors . AuthAttemptExpired ), err ):
2024-06-06 15:59:43 +02:00
return nil , handlers . ForbiddenError ()
2021-04-08 20:54:32 -04:00
default :
2021-07-28 06:31:16 -04:00
event . WriteError ( ctx , op , err , event . WithInfoMsg ( "error generating parameters for token request" ))
2024-06-06 15:59:43 +02:00
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Error generating parameters for token request. See the controller's log for more information." )
2021-04-08 20:54:32 -04:00
}
}
if token == nil {
2021-04-12 13:57:14 -05:00
return & pbs . AuthenticateResponse {
2022-04-11 14:50:29 -04:00
Command : req . Command ,
Attrs : & pbs . AuthenticateResponse_OidcAuthMethodAuthenticateTokenResponse {
OidcAuthMethodAuthenticateTokenResponse : & pb . OidcAuthMethodAuthenticateTokenResponse {
Status : "unknown" ,
},
},
2021-04-12 13:57:14 -05:00
}, nil
2021-04-08 20:54:32 -04:00
}
2021-05-04 19:57:35 -05:00
responseToken , err := s . ConvertInternalAuthTokenToApiAuthToken (
2021-04-08 20:54:32 -04:00
ctx ,
token ,
)
if err != nil {
2024-06-06 15:59:43 +02:00
event . WriteError ( ctx , op , err , event . WithInfoMsg ( "error converting response to proper format." ))
return nil , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Error converting response to proper format. See the controller's log for more information." )
2021-04-08 20:54:32 -04:00
}
return s . convertToAuthenticateResponse ( ctx , req , authResults , responseToken )
}
2024-08-29 17:14:42 -04:00
func validateAuthenticateOidcRequest ( _ context . Context , req * pbs . AuthenticateRequest ) error {
2021-04-08 20:54:32 -04:00
badFields := make ( map [ string ] string )
switch req . GetCommand () {
case startCommand :
2022-04-11 14:50:29 -04:00
if req . GetOidcStartAttributes () != nil {
attrs := req . GetOidcStartAttributes ()
2022-06-19 10:55:37 -04:00
switch {
case attrs == nil :
badFields [ "attributes" ] = "Attributes field not supplied request"
default :
// Ensure we pay no attention to cache information provided by the client
attrs . CachedRoundtripPayload = ""
payload := attrs . GetRoundtripPayload ()
if payload == nil {
break
}
m , err := json . Marshal ( payload . AsMap ())
if err != nil {
// We don't know what's in this payload so we swallow the
// error, as it could be something sensitive.
badFields [ roundtripPayloadAttributesField ] = "Unable to marshal given value as JSON."
} else {
// Cache for later
attrs . CachedRoundtripPayload = string ( m )
}
2021-04-08 20:54:32 -04:00
}
}
case callbackCommand :
2022-04-11 14:50:29 -04:00
attrs := req . GetOidcAuthMethodAuthenticateCallbackRequest ()
2022-06-19 10:55:37 -04:00
switch {
case attrs == nil :
badFields [ "attributes" ] = "Attributes field not supplied request"
return handlers . InvalidArgumentErrorf ( "This is a required field." , badFields )
default :
if attrs . GetCode () == "" && attrs . GetError () == "" {
badFields [ codeField ] = "Code field not supplied in callback request."
}
2021-04-08 20:54:32 -04:00
2022-06-19 10:55:37 -04:00
if attrs . GetState () == "" {
badFields [ stateField ] = "State field not supplied in callback request."
}
2021-04-08 20:54:32 -04:00
}
case tokenCommand :
2022-04-18 09:26:15 -04:00
tokenType := req . GetType ()
if tokenType == "" {
// Fall back to deprecated field if type is not set
tokenType = req . GetTokenType ()
}
tType := strings . ToLower ( strings . TrimSpace ( tokenType ))
2021-04-08 20:54:32 -04:00
if tType != "" && tType != "token" && tType != "cookie" {
badFields [ tokenTypeField ] = `The only accepted types are "token" and "cookie".`
}
default :
badFields [ commandField ] = "Invalid command for this auth method type."
}
if len ( badFields ) > 0 {
return handlers . InvalidArgumentErrorf ( "Invalid fields provided in request." , badFields )
}
return nil
}
2021-07-29 18:52:56 -06:00
func toStorageOidcAuthMethod ( ctx context . Context , scopeId string , in * pb . AuthMethod ) ( out * oidc . AuthMethod , dryRun , forced bool , err error ) {
2021-04-08 20:54:32 -04:00
const op = "authmethod_service.toStorageOidcAuthMethod"
if in == nil {
2023-06-06 17:09:08 -04:00
return nil , false , false , errors . New ( ctx , errors . InvalidParameter , op , "nil auth method." )
2021-04-08 20:54:32 -04:00
}
2022-04-08 11:40:59 -04:00
attrs := in . GetOidcAuthMethodsAttributes ()
2021-04-08 20:54:32 -04:00
clientId := attrs . GetClientId (). GetValue ()
clientSecret := oidc . ClientSecret ( attrs . GetClientSecret (). GetValue ())
var opts [] oidc . Option
if in . GetName () != nil {
opts = append ( opts , oidc . WithName ( in . GetName (). GetValue ()))
}
if in . GetDescription () != nil {
opts = append ( opts , oidc . WithDescription ( in . GetDescription (). GetValue ()))
}
if iss := strings . TrimSpace ( attrs . GetIssuer (). GetValue ()); iss != "" {
// Strip off everything after and including ".well-known/openid-configuration"
// but leave the "/" attached to the end.
iss = strings . SplitN ( iss , ".well-known/" , 2 )[ 0 ]
issuer , err := url . Parse ( iss )
if err != nil {
2023-06-06 17:09:08 -04:00
return nil , false , false , errors . Wrap ( ctx , err , op , errors . WithMsg ( "cannot parse issuer" ), errors . WithCode ( errors . InvalidParameter ))
2021-04-08 20:54:32 -04:00
}
opts = append ( opts , oidc . WithIssuer ( issuer ))
}
if apiUrl := strings . TrimSpace ( attrs . GetApiUrlPrefix (). GetValue ()); apiUrl != "" {
apiU , err := url . Parse ( apiUrl )
if err != nil {
2023-06-06 17:09:08 -04:00
return nil , false , false , errors . Wrap ( ctx , err , op , errors . WithMsg ( "cannot parse api_url_prefix" ), errors . WithCode ( errors . InvalidParameter ))
2021-04-08 20:54:32 -04:00
}
opts = append ( opts , oidc . WithApiUrl ( apiU ))
}
if attrs . GetMaxAge () != nil {
maxAge := attrs . GetMaxAge (). GetValue ()
if maxAge == 0 {
opts = append ( opts , oidc . WithMaxAge ( - 1 ))
} else {
opts = append ( opts , oidc . WithMaxAge ( int ( maxAge )))
}
}
var signAlgs [] oidc . Alg
for _ , a := range attrs . GetSigningAlgorithms () {
signAlgs = append ( signAlgs , oidc . Alg ( a ))
}
if len ( signAlgs ) > 0 {
opts = append ( opts , oidc . WithSigningAlgs ( signAlgs ... ))
}
2023-11-21 11:30:02 -05:00
var prompts [] oidc . PromptParam
for _ , a := range attrs . GetPrompts () {
prompts = append ( prompts , oidc . PromptParam ( a ))
}
if len ( prompts ) > 0 {
opts = append ( opts , oidc . WithPrompts ( prompts ... ))
}
2021-04-08 20:54:32 -04:00
if len ( attrs . GetAllowedAudiences ()) > 0 {
opts = append ( opts , oidc . WithAudClaims ( attrs . GetAllowedAudiences () ... ))
}
if len ( attrs . GetIdpCaCerts ()) > 0 {
2021-07-29 18:52:56 -06:00
certs , err := oidc . ParseCertificates ( ctx , attrs . GetIdpCaCerts () ... )
2021-04-08 20:54:32 -04:00
if err != nil {
return nil , false , false , err
}
opts = append ( opts , oidc . WithCertificates ( certs ... ))
}
2021-04-28 06:53:13 -04:00
if len ( attrs . GetClaimsScopes ()) > 0 {
opts = append ( opts , oidc . WithClaimsScopes ( attrs . GetClaimsScopes () ... ))
}
2021-05-04 08:41:04 -04:00
if len ( attrs . GetAccountClaimMaps ()) > 0 {
claimsMap := make ( map [ string ] oidc . AccountToClaim , len ( attrs . GetAccountClaimMaps ()))
for _ , v := range attrs . GetAccountClaimMaps () {
2021-07-29 18:52:56 -06:00
acm , err := oidc . ParseAccountClaimMaps ( ctx , v )
2021-05-04 08:41:04 -04:00
if err != nil {
2023-06-06 17:09:08 -04:00
return nil , false , false , errors . Wrap ( ctx , err , op )
2021-05-04 08:41:04 -04:00
}
if len ( acm ) > 1 {
2023-06-06 17:09:08 -04:00
return nil , false , false , errors . New ( ctx , errors . InvalidParameter , op , fmt . Sprintf ( "unable to parse account claim map %s" , v ))
2021-05-04 08:41:04 -04:00
}
2021-06-02 07:09:41 -04:00
var m oidc . ClaimMap
for _ , m = range acm {
2021-05-04 08:41:04 -04:00
}
2021-07-29 18:52:56 -06:00
to , err := oidc . ConvertToAccountToClaim ( ctx , m . To )
2021-05-04 08:41:04 -04:00
if err != nil {
2023-06-06 17:09:08 -04:00
return nil , false , false , errors . Wrap ( ctx , err , op )
2021-05-04 08:41:04 -04:00
}
2021-06-02 07:09:41 -04:00
claimsMap [ m . From ] = to
2021-05-04 08:41:04 -04:00
}
opts = append ( opts , oidc . WithAccountClaimMap ( claimsMap ))
}
2021-07-29 18:52:56 -06:00
u , err := oidc . NewAuthMethod ( ctx , scopeId , clientId , clientSecret , opts ... )
2021-04-08 20:54:32 -04:00
if err != nil {
return nil , false , false , handlers . ApiErrorWithCodeAndMessage ( codes . Internal , "Unable to build auth method: %v." , err )
}
return u , attrs . GetDryRun (), attrs . GetDisableDiscoveredConfigValidation (), nil
}