oauthoidc

package
v0.0.0-...-82ab749 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2024 License: BSD-3-Clause Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AzureADTenantId                    = "AZURE_AD_TENANT_ID"        // Lambda environment variable name
	AzureADTenantValueForNonAzureADIdP = "unused-by-non-AzureAD-IdP" // sentinel value
)
View Source
const (
	OAuthOIDCClientId              = "OAUTH_OIDC_CLIENT_ID"               // Lambda environment variable name
	OAuthOIDCClientSecret          = "OAuthOIDCClientSecret"              // Secrets Manager secret name
	OAuthOIDCClientSecretTimestamp = "OAUTH_OIDC_CLIENT_SECRET_TIMESTAMP" // Lambda environment variable name
)
View Source
const (
	OktaHostname                   = "OKTA_HOSTNAME"          // Lambda environment variable name
	OktaHostnameValueForGoogleIdP  = "unused-by-Google-IdP"   // old sentinel value
	OktaHostnameValueForNonOktaIdP = "unused-by-non-Okta-IdP" // new sentinel value
)

Variables

This section is empty.

Functions

func Nonce

func Nonce() (string, error)

Types

type Client

type Client struct {
	AccessToken string
	ClientId    string
	// contains filtered or unexported fields
}

func NewClient

func NewClient(
	ctx context.Context,
	cfg *awscfg.Config,
	clientId string,
	clientSecretTimestamp string,
	pathQualifier PathQualifier,
) (*Client, error)

func (*Client) Copy

func (c *Client) Copy() *Client

Copy returns a, yes, copy of the *Client with all its configuration _except_ the AccessToken, which we don't want to be sharing across multiple requests.

func (*Client) Get

func (c *Client) Get(path UnqualifiedPath, query url.Values, i interface{}) (*http.Response, []byte, error)

Get requests the given path with the given query string from the client's host and unmarshals the JSON response body into the given interface{}. It returns the *http.Response, though its Body field is not usable, and an error, if any.

func (*Client) GetURL

func (c *Client) GetURL(u *url.URL, query url.Values, i interface{}) (*http.Response, []byte, error)

func (*Client) IsAzureAD

func (c *Client) IsAzureAD() bool

func (*Client) IsGoogle

func (c *Client) IsGoogle() bool

func (*Client) IsOkta

func (c *Client) IsOkta() bool

func (*Client) Keys

func (c *Client) Keys() ([]*Key, error)

Keys returns the OAuth OIDC provider's current list of public keys, memoizing the response for the rest of this process's lifetime. Google's Cache-Control header suggests they rotate keys every few hours; Okta's suggests they rotate keys about every two months. This client is expected to run in Lambda so it seems safe to not invalidate.

func (*Client) Post

func (c *Client) Post(path UnqualifiedPath, body url.Values, i interface{}) (*http.Response, []byte, error)

Post requests the given path with the given body (form-encoded) from the client's host and unmarshals the JSON response body into the given interface{}. It returns the *http.Response, though its Body field is not usable, and an error, if any.

func (*Client) PostURL

func (c *Client) PostURL(u *url.URL, body url.Values, i interface{}) (*http.Response, []byte, error)

func (*Client) Provider

func (c *Client) Provider() Provider

func (*Client) RoleNameFromIdP

func (c *Client) RoleNameFromIdP(user string) (string, error)

func (*Client) URL

func (c *Client) URL(path UnqualifiedPath, query url.Values) *url.URL

func (*Client) WithAccessToken

func (c *Client) WithAccessToken(accessToken string) *Client

WithAccessToken returns a copy of the *Client with the AccessToken field set.

type IDToken

type IDToken struct {
	Address               map[string]string `json:"address"`
	Audience              string            `json:"aud"`
	AuthenticationMethods []string          `json:"amr"`
	AuthenticationTime    int64             `json:"auth_time"`
	DebugID               string            `json:"jti"`
	Email                 string            `json:"email"`
	EmailVerified         bool              `json:"email_verified"`
	Expires               int64             `json:"exp"`
	FamilyName            string            `json:"family_name"`
	GivenName             string            `json:"given_name"`
	Groups                []string          `json:"groups"`
	IdentityProvider      string            `json:"idp"`
	IssuedAt              int64             `json:"iat"`
	Issuer                string            `json:"iss"`
	Login                 string            `json:"login"`
	Locale                string            `json:"locale"`
	MiddleName            string            `json:"middle_name"`
	Name                  string            `json:"name"`
	Nonce                 string            `json:"nonce"`
	Nickname              string            `json:"nickname"`
	PhoneNumber           string            `json:"phone_number"`
	PreferredUsername     string            `json:"preferred_username"`
	ProfileURL            string            `json:"profile"`
	Subject               string            `json:"sub"`
	UpdatedAt             int64             `json:"updated_at"`
	Version               interface{}       `json:"ver"` // Azure AD encodes this as a string; Okta encodes this as an integer; fucking hell, folks
	ZoneInfo              string            `json:"zoneinfo"`
}

func (*IDToken) JSONString

func (t *IDToken) JSONString() (string, error)

func (*IDToken) Verify

func (t *IDToken) Verify(c *Client) error

type InvalidJWTError

type InvalidJWTError string

func (InvalidJWTError) Error

func (err InvalidJWTError) Error() string

type JWT

type JWT struct {
	Header    *JWTHeader
	Payload   JWTPayload
	Signature JWTSignature
	// contains filtered or unexported fields
}

func ParseAndVerifyJWT

func ParseAndVerifyJWT(s string, c *Client, p JWTPayload) (*JWT, error)

func ParseJWT

func ParseJWT(s string, p JWTPayload) (*JWT, error)

func (*JWT) Verify

func (jwt *JWT) Verify(c *Client) error

type JWTHeader

type JWTHeader struct {
	Algorithm string `json:"alg"`
	KeyID     string `json:"kid"` // maybe Okta-specific
}

type JWTPayload

type JWTPayload interface {
	Verify(c *Client) error
}

type JWTSignature

type JWTSignature []byte

type Key

type Key struct {
	Algorithm string `json:"alg"`
	Exponent  string `json:"e"` // comes base64-URL-encoded
	KeyID     string `json:"kid"`
	KeyType   string `json:"kty"`
	Modulus   string `json:"n"` // comes base64-URL-encoded
	Status    string `json:"status"`
	Use       string `json:"use"`
}

func (*Key) RSAPublicKey

func (k *Key) RSAPublicKey() (*rsa.PublicKey, error)

type KeyNotFoundError

type KeyNotFoundError string

func (KeyNotFoundError) Error

func (err KeyNotFoundError) Error() string

type KeysResponse

type KeysResponse struct {
	Keys []*Key `json:"keys"`
}

type MalformedJWTError

type MalformedJWTError string

func (MalformedJWTError) Error

func (err MalformedJWTError) Error() string

type OktaAccessToken

type OktaAccessToken struct {
	Audience string   `json:"aud"`
	ClientId string   `json:"cid"`
	DebugID  string   `json:"jti"`
	Expires  int64    `json:"exp"`
	IssuedAt int64    `json:"iat"`
	Issuer   string   `json:"iss"`
	Scopes   []string `json:"scp"`
	Subject  string   `json:"sub"`
	UserID   string   `json:"uid"`
	Version  int      `json:"ver"`
}

func (*OktaAccessToken) JSONString

func (t *OktaAccessToken) JSONString() (string, error)

func (*OktaAccessToken) Verify

func (t *OktaAccessToken) Verify(c *Client) error

type PathQualifier

type PathQualifier func(UnqualifiedPath) *url.URL

func AzureADPathQualifier

func AzureADPathQualifier(tenantId string) PathQualifier

func GooglePathQualifier

func GooglePathQualifier() PathQualifier

func OktaPathQualifier

func OktaPathQualifier(hostname string) PathQualifier

type Provider

type Provider string
const (
	AzureAD Provider = "Azure AD"
	Google  Provider = "Google"
	Okta    Provider = "Okta"
)

func IdPName

func IdPName(clientId string) Provider

IdPName detects what sort of IdP this is, definitively, and covering all the supported IdPs, from the structure of the client ID. If this ever becomes impossible then we'll have to ask or just name things so that it doesn't matter.

type State

type State struct {
	Next  string
	Nonce string
}

func ParseState

func ParseState(s string) (*State, error)

func (*State) String

func (s *State) String() string

type TokenResponse

type TokenResponse struct {
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
	AccessToken string `json:"access_token"`
	Scope       string `json:"scope"`
	IDToken     string `json:"id_token"`
}

type UndefinedRoleError

type UndefinedRoleError string

func (UndefinedRoleError) Error

func (err UndefinedRoleError) Error() string

type UnqualifiedPath

type UnqualifiedPath string
const (
	Authorize UnqualifiedPath = "authorize"
	Issuer    UnqualifiedPath = "issuer"
	Keys      UnqualifiedPath = "keys"
	Token     UnqualifiedPath = "token"
	User      UnqualifiedPath = "user" // not exactly ".well-known" but we need it from all providers
)

Names of well-known URLs in the OAuth OIDC flow. PathQualifiers will turn these into the actual fully-qualified URLs used by supported IdPs.

type VerificationError

type VerificationError struct {
	Field            string
	Actual, Expected string
}

func (VerificationError) Error

func (err VerificationError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL