openid

package
v0.0.0-...-053b097 Latest Latest
Warning

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

Go to latest
Published: Dec 2, 2024 License: Apache-2.0 Imports: 19 Imported by: 6

Documentation

Overview

Package openid contains functionality related to OpenID Connect protocol.

Index

Constants

View Source
const GoogleDiscoveryURL = "https://accounts.google.com/.well-known/openid-configuration"

GoogleDiscoveryURL is an URL of the Google OpenID Connect discovery document.

Variables

This section is empty.

Functions

func AudienceMatchesHost

func AudienceMatchesHost(ctx context.Context, r auth.RequestMetadata, aud string) (valid bool, err error)

AudienceMatchesHost can be used as a AudienceCheck callback.

It verifies token's audience matches "Host" request header. Suitable for environments where "Host" header can be trusted.

Types

type DiscoveryDoc

type DiscoveryDoc struct {
	Issuer                string `json:"issuer"`
	AuthorizationEndpoint string `json:"authorization_endpoint"`
	TokenEndpoint         string `json:"token_endpoint"`
	RevocationEndpoint    string `json:"revocation_endpoint"`
	JwksURI               string `json:"jwks_uri"`
}

DiscoveryDoc describes a subset of OpenID Discovery JSON document.

See https://developers.google.com/identity/protocols/OpenIDConnect#discovery.

func FetchDiscoveryDoc

func FetchDiscoveryDoc(ctx context.Context, url string) (*DiscoveryDoc, error)

FetchDiscoveryDoc fetches the discovery document from the given URL.

It is cached in the process cache for 24 hours.

func (*DiscoveryDoc) SigningKeys

func (d *DiscoveryDoc) SigningKeys(ctx context.Context) (*JSONWebKeySet, error)

SigningKeys returns a JSON Web Key set fetched from the location specified in the discovery document.

It fetches them on the first use and then keeps them cached in the process cache for 6h.

May return both fatal and transient errors.

type GoogleComputeAuthMethod

type GoogleComputeAuthMethod struct {
	// Header is a HTTP header to read the token from. Required.
	Header string
	// AudienceCheck is a callback to use to check tokens audience. Required.
	AudienceCheck func(ctx context.Context, r auth.RequestMetadata, aud string) (valid bool, err error)
	// contains filtered or unexported fields
}

GoogleComputeAuthMethod implements auth.Method by checking a header which is expected to have an OpenID Connect ID token generated via GCE VM identity metadata endpoint.

Such tokens identify a particular VM via `google.compute_engine` claim. ID tokens without that claim (even if they pass the signature checks) are rejected.

The authenticated identity has form "bot:<instance-name>@gce.<project>", but instead of parsing it, better to use GetGoogleComputeTokenInfo to get the information extracted from the token in a structured form.

func (*GoogleComputeAuthMethod) Authenticate

Authenticate extracts user information from the incoming request.

It returns:

  • (*User, nil, nil) on success.
  • (nil, nil, nil) if the method is not applicable.
  • (nil, nil, error) if the method is applicable, but credentials are bad.

func (*GoogleComputeAuthMethod) Warmup

Warmup prepares local caches. It's optional.

Implements auth.Warmable.

type GoogleComputeTokenInfo

type GoogleComputeTokenInfo struct {
	// Audience is the audience in the token as it was checked by AudienceCheck.
	Audience string
	// ServiceAccount is the service account email the GCE VM runs under.
	ServiceAccount string
	// Instance is a GCE VM instance name asserted in the token.
	Instance string
	// Zone is the GCE zone with the VM.
	Zone string
	// Project is a GCP project name the VM belong to.
	Project string
}

GoogleComputeTokenInfo contains information extracted from the GCM VM token.

func GetGoogleComputeTokenInfo

func GetGoogleComputeTokenInfo(ctx context.Context) *GoogleComputeTokenInfo

GetGoogleComputeTokenInfo returns GCE VM info as asserted by the VM token.

Works only from within a request handler and only if the call was authenticated via a GCE VM token. In all other cases (anonymous calls, calls authenticated via some other mechanism, etc.) returns nil.

type GoogleIDTokenAuthMethod

type GoogleIDTokenAuthMethod struct {
	// Audience is a list of allowed audiences for tokens that identify Google
	// service accounts ("*.gserviceaccount.com" emails).
	Audience []string

	// AudienceCheck is an optional callback to use to check tokens audience in
	// case enumerating all expected audiences is not viable.
	//
	// Works in conjunction with Audience. Also, just like Audience, this check is
	// used only for tokens that identify service accounts.
	AudienceCheck func(ctx context.Context, r auth.RequestMetadata, aud string) (valid bool, err error)

	// SkipNonJWT indicates to ignore tokens that don't look like JWTs.
	//
	// This is useful when chaining together multiple auth methods that all search
	// for tokens in the `Authorization` header.
	//
	// If the `Authorization` header contains a malformed JWT and SkipNonJWT is
	// false, Authenticate would return an error, which eventually would result in
	// Unauthenticated response code (e.g. HTTP 401). But If SkipNonJWT is true,
	// Authenticate would return (nil, nil, nil) instead, which (per auth.Method
	// API) instructs the auth stack to try the next registered authentication
	// method (or treat the request as anonymous if there are no more methods to
	// try).
	SkipNonJWT bool
	// contains filtered or unexported fields
}

GoogleIDTokenAuthMethod implements auth.Method by checking `Authorization` header which is expected to have an OpenID Connect ID token signed by Google.

The header value should have form "Bearer <base64 JWT>".

There are two variants of tokens signed by Google:

  • ID tokens identifying end users. They always have an OAuth2 Client ID as an audience (`aud` field). Their `aud` is placed into User.ClientID, so it is later checked against an allowlist of client IDs by the LUCI auth stack.
  • ID tokens identifying service accounts. They generally can have anything at all as an audience, but usually have an URL of the service being called. Their `aud` is first checked against Audience list and AudienceCheck callback below. If after these check the audience is still not recognized, but it looks like a Google OAuth2 Client ID, it is placed into User.ClientID, to be subjected to the regular check against an allowlist of OAuth2 Client IDs.

func (*GoogleIDTokenAuthMethod) Authenticate

Authenticate extracts user information from the incoming request.

It returns:

  • (*User, nil, nil) on success.
  • (nil, nil, nil) if the method is not applicable.
  • (nil, nil, error) if the method is applicable, but credentials are bad.

func (*GoogleIDTokenAuthMethod) Warmup

Warmup prepares local caches. It's optional.

Implements auth.Warmable.

type IDToken

type IDToken struct {
	Iss           string `json:"iss"`
	AtHash        string `json:"at_hash"`
	EmailVerified bool   `json:"email_verified"`
	Sub           string `json:"sub"`
	Azp           string `json:"azp"`
	Email         string `json:"email"`
	Profile       string `json:"profile"`
	Picture       string `json:"picture"`
	Name          string `json:"name"`
	Aud           string `json:"aud"`
	Iat           int64  `json:"iat"`
	Exp           int64  `json:"exp"`
	Nonce         string `json:"nonce"`
	Hd            string `json:"hd"`

	// This section is present only for tokens generated via GCE Metadata server
	// in "full" format.
	Google struct {
		ComputeEngine struct {
			InstanceCreationTimestamp int64  `json:"instance_creation_timestamp"`
			InstanceID                string `json:"instance_id"`
			InstanceName              string `json:"instance_name"`
			ProjectID                 string `json:"project_id"`
			ProjectNumber             int64  `json:"project_number"`
			Zone                      string `json:"zone"`
		} `json:"compute_engine"`
	} `json:"google"`
}

IDToken is a verified deserialized ID token.

See https://developers.google.com/identity/protocols/OpenIDConnect.

func UserFromIDToken

func UserFromIDToken(ctx context.Context, token string, discovery *DiscoveryDoc) (*IDToken, *auth.User, error)

UserFromIDToken validates the ID token and extracts user information from it.

Returns the partially validated token and auth.User extracted from it.

The caller is still responsible to verify token's Audience field.

func VerifyIDToken

func VerifyIDToken(ctx context.Context, token string, keys jwt.SignatureVerifier, issuer string) (*IDToken, error)

VerifyIDToken deserializes and verifies the ID token.

It checks the signature, expiration time and verifies fields `iss` and `email_verified`.

It checks `aud` and `sub` are present, but does NOT verify them any further. It is the caller's responsibility to do so.

This is a fast local operation.

type JSONWebKeySet

type JSONWebKeySet struct {
	// contains filtered or unexported fields
}

JSONWebKeySet implements subset of functionality described in RFC7517.

It currently supports only RSA keys and RS256 alg. It's intended to be used to represent keys fetched from https://www.googleapis.com/oauth2/v3/certs.

It's used to verify ID token signatures.

func NewJSONWebKeySet

func NewJSONWebKeySet(parsed *JSONWebKeySetStruct) (*JSONWebKeySet, error)

NewJSONWebKeySet makes the keyset from raw JSON Web Key set struct.

func (*JSONWebKeySet) CheckSignature

func (k *JSONWebKeySet) CheckSignature(keyID string, signed, signature []byte) error

CheckSignature returns nil if `signed` was indeed signed by the given key.

type JSONWebKeySetStruct

type JSONWebKeySetStruct struct {
	Keys []JSONWebKeyStruct `json:"keys"`
}

JSONWebKeySetStruct defines the JSON structure of JSONWebKeySet.

Read it from the wire and pass to NewJSONWebKeySet to get a usable object.

See https://www.iana.org/assignments/jose/jose.xhtml#web-key-parameters. We care only about RSA public keys (thus use 'n' and 'e').

type JSONWebKeyStruct

type JSONWebKeyStruct struct {
	Kty string `json:"kty"`
	Alg string `json:"alg"`
	Use string `json:"use"`
	Kid string `json:"kid"`
	N   string `json:"n"` // raw URL-safe base64, NOT standard base64
	E   string `json:"e"` // same
}

JSONWebKeyStruct defines the JSON structure of a single key in the key set.

Jump to

Keyboard shortcuts

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