gitkit

package
v0.0.0-...-8285038 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2016 License: Apache-2.0 Imports: 22 Imported by: 10

Documentation

Overview

Package gitkit provides convenient utilities for third party website to integrate Google Identity Toolkit.

See more at https://developers.google.com/identity-toolkit

To use Identity Toolkit Go client:

var client *gitkit.Client

func handleSignIn(w http.ResponseWriter, r *http.Request) {
	// If there is no valid session, check identity tookit ID token.
	ts := client.TokenFromRequest(r)
	token, err := client.ValidateToken(context.Background(), ts, []string{clientID})
	if err != nil {
		// Not a valid token. Handle error.
	}
	// Token is validate and it contains the user account information
	// including user ID, email address, etc.
	// Issue your own session cookie to finish the sign in.
}

func main() {
	// Provide configuration. gitkit.LoadConfig() can also be used to load
	// the configuration from a JSON file.
	config := &gitkit.Config{
		ClientID:	"123.apps.googleusercontent.com",
		WidgetURL:	"http://localhost/gitkit",
		CookieName:	"gtoken",
	}
	var err error
	client, err = gitkit.New(context.Background(), config)
	if err != nil {
		// Handle error.
	}

	// Provide HTTP handler.
	http.HandleFunc("/signIn", handleSignIn)
	// Start the server.
	log.Fatal(http.ListenAndServe(":8080", nil))
}

The integration with Google App Engine is similar except for the context variable should be created from the request, i.e., appengine.NewContext(r):

var client *gitkit.Client

func handleSignIn(w http.ResponseWriter, r *http.Request) {
	// If there is no valid session, check identity tookit ID token.
	ts := client.TokenFromRequest(r)
	token, err := client.ValidateToken(appengine.NewContext(r), ts, []string{clientID})
	if err != nil {
		// Not a valid token. Handle error.
	}
	// Token is validate and it contains the user account information
	// including user ID, email address, etc.
	// Issue your own session cookie to finish the sign in.
}

func init() {
	// Provide configuration. gitkit.LoadConfig() can also be used to load
	// the configuration from a JSON file.
	config := &gitkit.Config{
		ClientID:	"123.apps.googleusercontent.com",
		WidgetURL:	"http://localhost/gitkit",
		CookieName:	"gtoken",
	}
	// Set the JSON key file path if running dev server in local.
	if appengine.IsDevAppServer() {
		c.GoogleAppCredentialsPath = googleAppCredentialsPath
	}
	var err error
	client, err = gitkit.New(context.Background(), config)
	if err != nil {
		// Handle error.
	}

	// Provide HTTP handler.
	http.HandleFunc("/signIn", handleSignIn)
	// Start the server.
	log.Fatal(http.ListenAndServe(":8080", nil))
}

The Go client uses Google Application Default Credentials to access authentication required Identity Toolkit API. The credentials returned are determined by the environment the code is running in. Conditions are checked in the following order:

1. The environment variable GOOGLE_APPLICATION_CREDENTIALS is checked. If this variable is specified it should point to a file that defines the credentials. The simplest way to get a credential for this purpose is to create a service account using the Google Developers Console in the section APIs & Auth, in the sub-section Credentials. Create a service account or choose an existing one and select Generate new JSON key. Set the environment variable to the path of the JSON file downloaded.

2. If you have installed the Google Cloud SDK on your machine and have run the command gcloud auth login, your identity can be used as a proxy to test code calling APIs from that machine.

3. If you are running in Google App Engine production, the built-in service account associated with the application will be used.

4. If you are running in Google Compute Engine production, the built-in service account associated with the virtual machine instance will be used.

5. If none of these conditions is true, an error will occur.

See more about Google Application Default Credentials at https://developers.google.com/identity/protocols/application-default-credentials

If Application Default Credentials doesn't work for your use case, you can set GoogleAppCredentialsPath in the config to the JSON key file path.

Index

Constants

View Source
const (
	GET  httpMethod = "GET"
	POST httpMethod = "POST"
)
View Source
const (
	ResetPasswordRequestType = "PASSWORD_RESET"
	ChangeEmailRequestType   = "NEW_EMAIL_ACCEPT"
	VerifyEmailRequestType   = "VERIFY_EMAIL"
)

Request types accepted by identitytoolkit getOobConfirmationCode API.

View Source
const (
	DefaultWidgetModeParamName = "mode"
	DefaultCookieName          = "gtoken"
)
View Source
const (
	OOBActionParam           = "action"
	OOBEmailParam            = "email"
	OOBCAPTCHAChallengeParam = "challenge"
	OOBCAPTCHAResponseParam  = "response"
	OOBOldEmailParam         = "oldEmail"
	OOBNewEmailParam         = "newEmail"
	OOBCodeParam             = "oobCode"
)

Parameter names used to extract the OOB code request.

View Source
const (
	OOBActionChangeEmail   = "changeEmail"
	OOBActionVerifyEmail   = "verifyEmail"
	OOBActionResetPassword = "resetPassword"
)

Acceptable OOB code request types.

Variables

View Source
var (
	APIBaseURI = "https://www.googleapis.com/identitytoolkit"
	APIVersion = "v3"
	APIPath    = "relyingparty"
)

Identitytoolkit API endpoint URL common parts.

View Source
var (
	ErrMalformed        = errors.New("malfored token")
	ErrInvalidAlgorithm = errors.New("invalid algorithm")
	ErrInvalidIssuer    = errors.New("invalid issuer")
	ErrInvalidAudience  = errors.New("invalid audience")
	ErrInvalidSignature = errors.New("invalid signature")
	ErrKeyNotFound      = errors.New("key not found")
	ErrExpired          = errors.New("token expired")
	ErrMissingAudience  = errors.New("missing audiences for token validation")
)

Errors that can be returned from the VerifyToken function.

Functions

func ErrorResponse

func ErrorResponse(err error) string

ErrorResponse generates a JSON error response from the given error.

func SuccessResponse

func SuccessResponse() string

SuccessResponse generates a JSON response which indicates the request is processed successfully.

Types

type APIClient

type APIClient struct {
	http.Client
}

An APIClient is an HTTP client that sends requests and receives responses from identitytoolkit APIs.

The underlying http.Client should add appropriate auth credentials according to the auth level of the API.

func (*APIClient) DeleteAccount

func (c *APIClient) DeleteAccount(req *DeleteAccountRequest) (*DeleteAccountResponse, error)

DeleteAccount deletes an account.

func (*APIClient) DownloadAccount

func (c *APIClient) DownloadAccount(req *DownloadAccountRequest) (*DownloadAccountResponse, error)

DownloadAccount donwloads accounts from identitytoolkit service.

func (*APIClient) GetAccountInfo

func (c *APIClient) GetAccountInfo(req *GetAccountInfoRequest) (*GetAccountInfoResponse, error)

GetAccountInfo retreives the users' account information.

func (*APIClient) GetOOBCode

func (c *APIClient) GetOOBCode(req *GetOOBCodeRequest) (*GetOOBCodeResponse, error)

GetOOBCode retrieves an OOB code.

func (*APIClient) GetProjectConfig

func (c *APIClient) GetProjectConfig() (*GetProjectConfigResponse, error)

GetProjectConfig retrieves the configuration information for the project.

func (*APIClient) SetAccountInfo

func (c *APIClient) SetAccountInfo(req *SetAccountInfoRequest) (*SetAccountInfoResponse, error)

SetAccountInfo updates the account information.

func (*APIClient) UploadAccount

func (c *APIClient) UploadAccount(req *UploadAccountRequest) (*UploadAccountResponse, error)

UploadAccount uploads accounts to identitytoolkit service.

type Bytes

type Bytes []byte

Bytes is a slice of bytes. It is URL safe Base64 instead of standard Base64 encoded when being marshalled to JSON.

func (Bytes) MarshalJSON

func (b Bytes) MarshalJSON() ([]byte, error)

MarshalJSON encodes the byte slice to a web safe base64 string.

func (*Bytes) UnmarshalJSON

func (b *Bytes) UnmarshalJSON(src []byte) error

UnmarshalJSON decodes a web safe base64 string into a byte slice.

type Certificates

type Certificates struct {
	URL string // Certificates URL.
	// contains filtered or unexported fields
}

Certificates contains a set of availabe identitytoolkit public certificates which are indexed by key IDs ("kid"). It caches the certificates according to the HTTP response cache setting and refetches them upon cache expiring. It is safe to use a Certificates from multiple concurrent goroutines.

func (*Certificates) Cert

func (c *Certificates) Cert(keyID string) (*x509.Certificate, error)

Cert returns the public certificate for the given key ID.

func (*Certificates) LoadIfNecessary

func (c *Certificates) LoadIfNecessary(transport http.RoundTripper) error

LoadIfNecessary downloads the certificates if there are no cached ones or the cache expired.

type Client

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

Client provides convenient utilities for integrating identitytoolkit service into a web service.

func New

func New(ctx context.Context, config *Config) (*Client, error)

New creates a Client from the configuration.

func (*Client) DeleteUser

func (c *Client) DeleteUser(ctx context.Context, user *User) error

DeleteUser deletes a user specified by the local ID.

func (*Client) GenerateChangeEmailOOBCode

func (c *Client) GenerateChangeEmailOOBCode(
	ctx context.Context, req *http.Request, email, newEmail, token string) (*OOBCodeResponse, error)

GenerateChangeEmailOOBCode generates an OOB code for changing email address.

If WidgetURL is not provided in the configuration, the OOBCodeURL field in the returned OOBCodeResponse is nil.

func (*Client) GenerateOOBCode

func (c *Client) GenerateOOBCode(ctx context.Context, req *http.Request) (*OOBCodeResponse, error)

GenerateOOBCode generates an OOB code based on the request.

func (*Client) GenerateResetPasswordOOBCode

func (c *Client) GenerateResetPasswordOOBCode(
	ctx context.Context, req *http.Request, email, captchaChallenge, captchaResponse string) (*OOBCodeResponse, error)

GenerateResetPasswordOOBCode generates an OOB code for resetting password.

If WidgetURL is not provided in the configuration, the OOBCodeURL field in the returned OOBCodeResponse is nil.

func (*Client) GenerateVerifyEmailOOBCode

func (c *Client) GenerateVerifyEmailOOBCode(
	ctx context.Context, req *http.Request, email string) (*OOBCodeResponse, error)

GenerateVerifyEmailOOBCode generates an OOB code for verifying email address.

If WidgetURL is not provided in the configuration, the OOBCodeURL field in the returned OOBCodeResponse is nil.

func (*Client) GetProjectConfig

func (c *Client) GetProjectConfig(ctx context.Context) (*ProjectConfig, error)

GetProjectConfig gets the Gitkit configuration of this project.

func (*Client) ListUsers

func (c *Client) ListUsers(ctx context.Context) *UserList

ListUsers lists all the users.

For example,

l := c.ListUsers()
for {
	for u := range l.C {
		// Do something
	}
	if l.Error != nil {
		l.Retry()
	} else {
		break
	}
}

func (*Client) ListUsersN

func (c *Client) ListUsersN(ctx context.Context, n int, pageToken string) ([]*User, string, error)

ListUsersN lists the next n users. For the first n users, the pageToken should be empty. Upon success, the users and pageToken for next n users are returned.

func (*Client) TokenFromRequest

func (c *Client) TokenFromRequest(req *http.Request) string

TokenFromRequest extracts the ID token from the HTTP request if present.

func (*Client) UpdateUser

func (c *Client) UpdateUser(ctx context.Context, user *User) error

UpdateUser updates the account information of the user.

func (*Client) UploadUsers

func (c *Client) UploadUsers(ctx context.Context, users []*User, algorithm string, key, saltSeparator []byte) error

UploadUsers uploads the users to identitytoolkit service. algorithm, key, saltSeparator specify the password hash algorithm, signer key and separator between password and salt accordingly.

func (*Client) UserByEmail

func (c *Client) UserByEmail(ctx context.Context, email string) (*User, error)

UserByEmail retrieves the account information of the user specified by the email address.

func (*Client) UserByLocalID

func (c *Client) UserByLocalID(ctx context.Context, localID string) (*User, error)

UserByLocalID retrieves the account information of the user specified by the local ID.

func (*Client) UserByToken

func (c *Client) UserByToken(ctx context.Context, token string, audiences []string) (*User, error)

UserByToken retrieves the account information of the user specified by the ID token.

func (*Client) ValidateToken

func (c *Client) ValidateToken(ctx context.Context, token string, audiences []string) (*Token, error)

ValidateToken validates the ID token and returns a Token.

Beside verifying the token is a valid JWT, it also validates that the token is not expired and is issued to the client with the given audiences.

type Config

type Config struct {
	// WidgetURL is the identitytoolkit javascript widget URL.
	// It is used to generate the reset password or change email URL and
	// could be an absolute URL, an absolute path or a relative path.
	WidgetURL string `json:"widgetUrl,omitempty"`
	// WidgetModeParamName is the parameter name used by the javascript widget.
	// A default value is used if left unspecified. If the parameter name is set
	// to other value in the javascript widget, this field should be set to the
	// same value.
	WidgetModeParamName string `json:"widgetModeParamName,omitempty"`
	// CookieName is the name of the cookie that stores the ID token.
	CookieName string `json:"cookieName,omitempty"`
	// GoogleAppCredentialsPath is the path of the service account JSON key file
	// downloaded from Google cloud console.
	// Only specify it if you cannot use Google Application Default Credentials.
	// See https://developers.google.com/identity/protocols/application-default-credentials
	// for more details about Application Default Credentials.
	GoogleAppCredentialsPath string `json:"googleAppCredentialsPath",omitempty"`
}

Config contains the configurations for creating a Client.

func LoadConfig

func LoadConfig(path string) (*Config, error)

LoadConfig loads the configuration from the config file specified by path.

type DeleteAccountRequest

type DeleteAccountRequest struct {
	LocalID string `json:"localId,omitempty"`
}

DeleteAccountRequest contains the user ID to be deleted.

type DeleteAccountResponse

type DeleteAccountResponse struct {
}

DeleteAccountResponse is the response for a DeleteAccountRequest upon success. It is an empty response.

type DownloadAccountRequest

type DownloadAccountRequest struct {
	MaxResults    int    `json:"maxResults,omitempty"`
	NextPageToken string `json:"nextPageToken,omitempty"`
}

DownloadAccountRequest contains the information for downloading accounts. MaxResults specifies the max number of accounts in one response. NextPageToken should be empty for the first request and the value from the previous response afterwards.

type DownloadAccountResponse

type DownloadAccountResponse struct {
	Users         []*User `json:"users,omitempty"`
	NextPageToken string  `json:"nextPageToken,omitempty"`
}

DownloadAccountResponse contains the downloaded accounts and the page token for next request.

type GetAccountInfoRequest

type GetAccountInfoRequest struct {
	Emails   []string `json:"email,omitempty"`
	LocalIDs []string `json:"localId,omitempty"`
}

GetAccountInfoRequest contains the email addresses or user IDs which are used to retrieve the user account information.

type GetAccountInfoResponse

type GetAccountInfoResponse struct {
	Users []*User `json:"users,omitempty"`
}

GetAccountInfoResponse contains the user account information specified by the corresponding GetAccountInfoRequest upon success.

type GetOOBCodeRequest

type GetOOBCodeRequest struct {
	RequestType      string `json:"requestType,omitempty"`
	Email            string `json:"email,omitempty"`
	CAPTCHAChallenge string `json:"challenge,omitempty"`
	CAPTCHAResponse  string `json:"captchaResp,omitempty"`
	NewEmail         string `json:"newEmail,omitempty"`
	Token            string `json:"idToken,omitempty"`
	UserIP           string `json:"userIp,omitempty"`
}

GetOOBCodeRequest contains the information to get an OOB code from identitytoolkit service.

There are three kinds of OOB code:

1. OOB code for password recovery. The RequestType should be PASSWORD_RESET and Email, CAPTCHAChallenge and CAPTCHAResponse are required.

2. OOB code for email change. The RequestType should be NEW_EMAIL_ACCEPT and Email, newEmail and Token are required.

3. OOB code for email verification. The RequestType should be VERIFY_EMAIL and Email is required.

type GetOOBCodeResponse

type GetOOBCodeResponse struct {
	OOBCode string `json:"oobCode,omitempty"`
}

GetOOBCodeResponse contains the OOB code upon success.

type GetProjectConfigResponse

type GetProjectConfigResponse struct {
	ProjectID         string       `json:"projectId,omitempty"`
	APIKey            string       `json:"apiKey,omitempty"`
	AllowPasswordUser bool         `json:"allowPasswordUser,omitempty"`
	IdpConfigs        []*IdpConfig `json:"idpConfig,omitempty"`
}

GetProjectConfigResponse contains the project ID, API key, whether password login is enabled and a list of IDP configs.

type IdpConfig

type IdpConfig struct {
	Provider string `json:"provider,omitempty"`
	Enabled  bool   `json:"enabled,omitempty"`
	ClientID string `json:"clientId,omitempty"`
}

IdpConfig holds the IDP configuration.

type OOBCodeResponse

type OOBCodeResponse struct {
	// Action identifies the request type.
	Action string
	// The email address of the user.
	Email string
	// The new email address of the user.
	// This field is only populated when Action is OOBActionChangeEmail.
	NewEmail string
	// The OOB confirmation code.
	OOBCode string
	// The URL that contains the OOB code and can be sent to the user for
	// confirming the action, e.g., sending the URL to the email address and
	// the user can click the URL to continue to reset the password.
	// It can be nil if WidgetURL is not provided in the configuration.
	OOBCodeURL *url.URL
}

OOBCodeResponse wraps the OOB code response.

type ProjectConfig

type ProjectConfig struct {
	// BrowserAPIKey is the API key used to call Google API in web browser.
	BrowserAPIKey string `json:"browserApiKey,omitempty"`
	// ClientID is the Google OAuth2 client ID for the server.
	ClientID string `json:"clientId,omitempty"`
	// SignInOptions are the sign in methods provided to users for sign in.
	SignInOptions []string `json:"signInOptions,omitempty"`
}

ProjectConfig contains the Gitkit configurations of the project.

type ProviderUserInfo

type ProviderUserInfo struct {
	// ProviderID is the identifer for the IDP, usually the TLD, e.g., google.com.
	ProviderID string `json:"providerId,omitempty"`
	// FederatedID is a unique identifier for the user within the IDP.
	FederatedID string `json:"federatedId,omitempty"`
	// DisplayName is the name of the user at the IDP.
	DisplayName string `json:"displayName,omitempty"`
	// PhotoURL is the profile picture URL of the user at the IDP.
	PhotoURL string `json:"photoUrl,omitempty"`
}

ProviderUserInfo holds the user information from an identity provider (IDP).

type SetAccountInfoRequest

type SetAccountInfoRequest struct {
	LocalID       string `json:"localId,omitempty"`
	Email         string `json:"email,omitempty"`
	DisplayName   string `json:"displayName,omitempty"`
	Password      string `json:"password,omitempty"`
	EmailVerified bool   `json:"emailVerified,omitempty"`
}

SetAccountInfoRequest contains account information to update. Either LocalID or Email should be provided to find the account. The Password field contains the new raw password if provided.

type SetAccountInfoResponse

type SetAccountInfoResponse struct {
}

SetAccountInfoResponse is the response for a SetAccountInfoRequest upon success. It is an empty response.

type TimestampMilli

type TimestampMilli float64

TimestampMilli represents the Unix time in milliseconds. float64 is used here as the underlying type because the API returns a float.

func (TimestampMilli) AsTime

func (t TimestampMilli) AsTime() time.Time

AsTime converts the TimestampMilli into a time.Time.

func (TimestampMilli) String

func (t TimestampMilli) String() string

String implements the fmt.Stringer interface.

type Token

type Token struct {
	// Issuer identifies the issuer of the ID token.
	Issuer string
	// Audience identifies the client that this ID token is intended for.
	Audience string
	// IssueAt is the time at which this ID token was issued.
	IssueAt time.Time
	// ExpireAt is the expiration time on or after which the ID token must not
	// be accepted for processing.
	ExpireAt time.Time
	// LocalID is the locally unique identifier within the client for the user.
	LocalID string
	// Email is the email address of the user.
	Email string
	// EmailVerified indicates whether or not the email address of the user has
	// been verifed.
	EmailVerified bool
	// ProviderID is the identifier for the identity provider (IDP) for the
	// user. It is usually the top level domain of the IDP, e.g., google.com.
	ProviderID string
	// DisplayName is the name that the user wants to be referred to.
	DisplayName string
	// PhotoURL is the URL of the user's profile picture.
	PhotoURL string
	// The token string.
	TokenString string
}

Token is a verified ID token issued by identitytoolkit service. See http://openid.net/specs/openid-connect-core-1_0.html#IDToken for more information about ID token.

func VerifyToken

func VerifyToken(token string, audiences []string, issuers []string, certs *Certificates) (*Token, error)

VerifyToken verifies the JWT is valid and signed by identitytoolkit service and returns the verfied token. A token is valid if and only if it passes the following checks: 1. The value of "iss" field is one of the issuers if issuers is not nil; 2. The value of "aud" field is the same as the audience; 3. The token is not expired according to the "exp" field; 4. The signature can be verified from one of the certs;

func (*Token) Expired

func (t *Token) Expired() bool

Expired checks whether or not the ID token is expired.

type UploadAccountRequest

type UploadAccountRequest struct {
	Users         []*User `json:"users,omitempty"`
	HashAlgorithm string  `json:"hashAlgorithm,omitempty"`
	SignerKey     Bytes   `json:"signerKey,omitempty"`
	SaltSeparator Bytes   `json:"saltSeparator,omitempty"`
}

UploadAccountRequest the account information of users to upload. The hash algorithm and signer key for the password are required.

type UploadAccountResponse

type UploadAccountResponse struct {
	Error UploadError `json:"error,omitempty"`
}

UploadAccountResponse contains the error information if some accounts are failed to upload.

type UploadError

type UploadError []*struct {
	// Index indicates the index of the failed account.
	Index int `json:"index,omitempty"`
	// Message is the uploading error message for the failed account.
	Message string `json:"message,omitempty"`
}

UploadError is the error object for partial upload failure.

func (UploadError) Error

func (e UploadError) Error() string

Error implements error interface.

type User

type User struct {
	// LocalID is the locally unique identifier for the user.
	LocalID string `json:"localId,omitempty"`
	// Email is the email address of the user.
	Email string `json:"email,omitempty"`
	// EmailVerified indicates if the email address of the user has been verifed.
	EmailVerified bool `json:"emailVerified,omitempty"`
	// DisplayName is the current name of the user. For instance, if the user
	// currently signs in with Google, the DisplayName is the one from Google IDP.
	DisplayName string `json:"displayName,omitempty"`
	// PhotoURL is the current profile picture URL of the user. For instance, if the
	// user currently signs in with Google, the PhotoURL is the one from Google IDP.
	PhotoURL string `json:"photoUrl,omitempty"`
	// ProviderUserInfo holds user information from all IDPs.
	ProviderUserInfo []ProviderUserInfo `json:"providerUserInfo,omitempty"`
	// PasswordHash is the hashed user password.
	PasswordHash Bytes `json:"passwordHash,omitempty"`
	// PasswordUpdateAt is the Unix time in milliseconds of the last password update.
	PasswordUpdateAt TimestampMilli `json:"passwordUpdateAt,omitempty"`
	// Salt is the salt used for hashing password.
	Salt Bytes `json:"salt,omitempty"`
	// ProviderID, if present, indicates the IDP with which the user signs in.
	ProviderID string `json:"providerId,omitempty"`
	// Password is the raw password of the user. It is only used to set new password.
	Password string `json:"-"`
}

User holds the user account information.

type UserList

type UserList struct {
	C     <-chan *User // The channel on which the users are delivered.
	Error error        // Indicates an error occurs when listing the users.
	// contains filtered or unexported fields
}

A UserList holds a channel that delivers all the users.

func (*UserList) Retry

func (l *UserList) Retry(ctx context.Context)

Retry resets Error to nil and resumes the downloading.

Jump to

Keyboard shortcuts

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