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

Typed errors for the verifier #405

Open
wants to merge 2 commits into
base: v3
Choose a base branch
from
Open
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
43 changes: 43 additions & 0 deletions oidc/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package oidc

import (
"fmt"
"time"
)

// TokenExpiredError indicates that Verify failed because the token was expired. This
// error does NOT indicate that the token is not also invalid for other reasons. Other
// checks might have failed if the expiration check had not failed.
type TokenExpiredError struct {
// Expiry is the time when the token expired.
Expiry time.Time
}

func (e *TokenExpiredError) Error() string {
return fmt.Sprintf("oidc: token is expired (Token Expiry: %v)", e.Expiry)
}

// InvalidIssuerError indicates that Verify failed because the token was issued
// by an unexpected issuer. This error does NOT indicate that the token is not
// also invalid for other reasons. Other checks might have failed if the issuer
// check had not failed.
type InvalidIssuerError struct {
Expected, Actual string
}

func (e *InvalidIssuerError) Error() string {
return fmt.Sprintf("oidc: id token issued by a different provider, expected %q got %q", e.Expected, e.Actual)
}

// InvalidAudienceError indicates that Verify failed because the token was
// intended for a different audience. This error does NOT indicate that the
// token is not also invalid for other reasons. Other checks might have failed
// if the audience check had not failed.
type InvalidAudienceError struct {
Expected string
Actual []string
}

func (e *InvalidAudienceError) Error() string {
return fmt.Sprintf("oidc: expected audience %q got %q", e.Expected, e.Actual)
}
18 changes: 3 additions & 15 deletions oidc/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,7 @@ const (
issuerGoogleAccountsNoScheme = "accounts.google.com"
)

// TokenExpiredError indicates that Verify failed because the token was expired. This
// error does NOT indicate that the token is not also invalid for other reasons. Other
// checks might have failed if the expiration check had not failed.
type TokenExpiredError struct {
// Expiry is the time when the token expired.
Expiry time.Time
}

func (e *TokenExpiredError) Error() string {
return fmt.Sprintf("oidc: token is expired (Token Expiry: %v)", e.Expiry)
}

// KeySet is a set of publc JSON Web Keys that can be used to validate the signature
// KeySet is a set of public JSON Web Keys that can be used to validate the signature
// of JSON web tokens. This is expected to be backed by a remote key set through
// provider metadata discovery or an in-memory set of keys delivered out-of-band.
type KeySet interface {
Expand Down Expand Up @@ -264,7 +252,7 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
//
// We will not add hooks to let other providers go off spec like this.
if !(v.issuer == issuerGoogleAccounts && t.Issuer == issuerGoogleAccountsNoScheme) {
return nil, fmt.Errorf("oidc: id token issued by a different provider, expected %q got %q", v.issuer, t.Issuer)
return nil, &InvalidIssuerError{Expected: v.issuer, Actual: t.Issuer}
}
}

Expand All @@ -274,7 +262,7 @@ func (v *IDTokenVerifier) Verify(ctx context.Context, rawIDToken string) (*IDTok
if !v.config.SkipClientIDCheck {
if v.config.ClientID != "" {
if !contains(t.Audience, v.config.ClientID) {
return nil, fmt.Errorf("oidc: expected audience %q got %q", v.config.ClientID, t.Audience)
return nil, &InvalidAudienceError{Expected: v.config.ClientID, Actual: t.Audience}
}
} else {
return nil, fmt.Errorf("oidc: invalid configuration, clientID must be provided or SkipClientIDCheck must be set")
Expand Down