func createToken(ctx context.Context, channelID string) (string, error) {
	iss, err := appengine.ServiceAccount(ctx)
	if err != nil {
		return "", err
	}
	iat := time.Now().Unix()
	jwt := map[string]interface{}{
		"iss": iss,
		"sub": iss,
		"aud": "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
		"iat": iat,
		"exp": iat + 3600, // 1 hour
		"uid": channelID,
	}
	body, err := json.Marshal(jwt)
	if err != nil {
		return "", err
	}
	header := base64.StdEncoding.EncodeToString([]byte(`{"typ":"JWT","alg":"RS256"}`))
	payload := append([]byte(header), byte('.'))
	payload = append(payload, []byte(base64.StdEncoding.EncodeToString(body))...)
	_, sig, err := appengine.SignBytes(ctx, payload)
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%s.%s", payload, base64.StdEncoding.EncodeToString(sig)), nil
}
// Taken from http://stackoverflow.com/a/26579165/196964 and
// https://cloud.google.com/storage/docs/access-control#Signed-URLs
func generateSignedURLs(c context.Context, host, resource string, expiry time.Time, httpVerb, contentMD5, contentType string) (string, error) {
	sa, err := appengine.ServiceAccount(c)
	if err != nil {
		return "", err
	}
	expiryStr := strconv.FormatInt(expiry.Unix(), 10)
	// The optional components should be the empty string.
	// https://cloud.google.com/storage/docs/access-control#Construct-the-String
	components := []string{
		httpVerb,    // PUT, GET, DELETE (but not POST)
		contentMD5,  // Optional. The MD5 digest value in base64. Client must provide same value if present.
		contentType, // Optional. Client must provide same value if present.
		expiryStr,   // Unix timestamp
		resource,    // /bucket/objectname
	}
	unsigned := strings.Join(components, "\n")
	_, b, err := appengine.SignBytes(c, []byte(unsigned))
	if err != nil {
		return "", err
	}
	sig := base64.StdEncoding.EncodeToString(b)
	p := url.Values{
		"GoogleAccessId": {sa},
		"Expires":        {expiryStr},
		"Signature":      {sig},
	}
	return fmt.Sprintf("%s%s?%s", host, resource, p.Encode()), err
}
Exemple #3
0
func (g giImpl) ServiceAccount() (string, error) {
	return appengine.ServiceAccount(g.aeCtx)
}