code: func computeDetachedSig(content, tokenID, tokenSecret string) (string, error) {
  	jwk := &jose.JSONWebKey{
  		Key:   []byte(tokenSecret),
  		KeyID: tokenID,
  	}
  
  	opts := &jose.SignerOptions{
  		// Since this is a symmetric key, go-jose doesn't automatically include
  		// the KeyID as part of the protected header. We have to pass it here
  		// explicitly.
  		ExtraHeaders: map[jose.HeaderKey]interface{}{
  			"kid": tokenID,
  		},
  	}
  
  	signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: jwk}, opts)
  	if err != nil {
  		return "", fmt.Errorf("can't make a HS256 signer from the given token: %v", err)
  	}
  
  	jws, err := signer.Sign([]byte(content))
  	if err != nil {
  		return "", fmt.Errorf("can't HS256-sign the given token: %v", err)
  	}
  
  	fullSig, err := jws.CompactSerialize()
  	if err != nil {
  		return "", fmt.Errorf("can't serialize the given token: %v", err)
  	}
  	return stripContent(fullSig)
  }
docs: // computeDetachedSig takes content and token details and computes a detached
  // JWS signature.  This is described in Appendix F of RFC 7515.  Basically, this
  // is a regular JWS with the content part of the signature elided.