@@ -372,25 +372,36 @@ type VerifyTokenOpts struct {
372372//
373373// The optional options allow specifying additional verifications on the identity.
374374func VerifyToken (opts VerifyTokenOpts ) (* api.GovalReplIdentity , error ) {
375+ identity , _ , err := VerifyTokenWithCertificate (opts )
376+ return identity , err
377+ }
378+
379+ // VerifyTokenWithCertificate verifies that the given `REPL_IDENTITY` value is
380+ // in fact signed by Goval's chain of authority, and addressed to the provided
381+ // audience (the `REPL_ID` of the recipient). Returns the identity and the
382+ // signing authority (a.k.a. the certificate).
383+ //
384+ // The options allow specifying additional verifications on the identity.
385+ func VerifyTokenWithCertificate (opts VerifyTokenOpts ) (* api.GovalReplIdentity , * api.GovalSigningAuthority , error ) {
375386 v , bytes , _ , err := verifyChain (opts .Message , opts .GetPubKey )
376387 if err != nil {
377- return nil , fmt .Errorf ("failed verify message: %w" , err )
388+ return nil , nil , fmt .Errorf ("failed verify message: %w" , err )
378389 }
379390
380391 signingAuthority , err := getSigningAuthority (opts .Message )
381392 if err != nil {
382- return nil , fmt .Errorf ("failed to read body type: %w" , err )
393+ return nil , nil , fmt .Errorf ("failed to read body type: %w" , err )
383394 }
384395
385396 var identity api.GovalReplIdentity
386397
387398 switch signingAuthority .GetVersion () {
388399 case api .TokenVersion_BARE_REPL_TOKEN :
389- return nil , errors .New ("wrong type of token provided" )
400+ return nil , nil , errors .New ("wrong type of token provided" )
390401 case api .TokenVersion_TYPE_AWARE_TOKEN :
391402 err = proto .Unmarshal (bytes , & identity )
392403 if err != nil {
393- return nil , fmt .Errorf ("failed to decode body: %w" , err )
404+ return nil , nil , fmt .Errorf ("failed to decode body: %w" , err )
394405 }
395406 }
396407
@@ -402,32 +413,32 @@ func VerifyToken(opts VerifyTokenOpts) (*api.GovalReplIdentity, error) {
402413 }
403414 }
404415 if ! validAudience {
405- return nil , fmt .Errorf ("message identity mismatch. expected %q, got %q" , opts .Audience , identity .Aud )
416+ return nil , nil , fmt .Errorf ("message identity mismatch. expected %q, got %q" , opts .Audience , identity .Aud )
406417 }
407418
408419 err = v .checkClaimsAgainstToken (& identity )
409420 if err != nil {
410- return nil , fmt .Errorf ("claim mismatch: %w" , err )
421+ return nil , nil , fmt .Errorf ("claim mismatch: %w" , err )
411422 }
412423
413424 if v .claims != nil {
414425 for _ , flag := range opts .Flags {
415426 if _ , ok := v .claims .Flags [flag ]; ! ok {
416- return nil , fmt .Errorf ("token not authorized for flag %s" , flag )
427+ return nil , nil , fmt .Errorf ("token not authorized for flag %s" , flag )
417428 }
418429 }
419430 } else if len (opts .Flags ) > 0 {
420- return nil , fmt .Errorf ("token not authorized for flags" )
431+ return nil , nil , fmt .Errorf ("token not authorized for flags" )
421432 }
422433
423434 for _ , option := range opts .Options {
424435 err = option .verify (& identity )
425436 if err != nil {
426- return nil , err
437+ return nil , nil , err
427438 }
428439 }
429440
430- return & identity , nil
441+ return & identity , signingAuthority , nil
431442}
432443
433444type verifyRawClaimsOpts struct {
0 commit comments