Generate Video Access token (JWT) with Twillio Go SDK - go

I am failing to create an Access Token for the Twillio Video Product with the golang SDK
In the docs there is golang sadly not mentioned
Does anyone of you know how I can create the required access token?
The JWT package mentioned in the examples of the other languages can not be found in the Go SDK.

I found that it is just not possible to do it with the default go SDK. I did follow the instructions on https://www.twilio.com/docs/iam/access-tokens and build the JWT myself. Maybe someone will find the solution handy:
package main
import (
"encoding/json"
"fmt"
"github.com/dvsekhvalnov/jose2go"
"log"
"time"
)
func main() {
accountSid := "XXX"
keySid := "YYY"
keySecret := "ZZZ"
username := "Simon"
roomName := "SimonsRoom"
now := time.Now()
type JWTPayload struct {
Jti string `json:"jti"`
Issuer string `json:"iss"`
Subject string `json:"sub"`
CreationUnixTimestamp int64 `json:"iat"`
NotBeforeUnixTimestamp int64 `json:"nbf"`
ExpiresUnixTimestamp int64 `json:"exp"`
Grants struct {
Identity string `json:"identity"`
Video struct {
Room string `json:"room"`
} `json:"video"`
} `json:"grants"`
}
payload := JWTPayload{
Jti: fmt.Sprintf("%s-%d",keySid,now.UnixNano()),
Issuer: keySid,
Subject: accountSid,
CreationUnixTimestamp: now.Unix(),
NotBeforeUnixTimestamp: now.Unix(),
ExpiresUnixTimestamp: now.Add(23*time.Hour).Unix(),
Grants: struct {
Identity string `json:"identity"`
Video struct {
Room string `json:"room"`
} `json:"video"`
}{
Identity: username,
Video: struct {
Room string `json:"room"`
}{
Room: roomName,
},
},
}
payloadByte, err := json.Marshal(payload)
if err != nil {
log.Fatal(err)
}
token, err := jose.SignBytes(payloadByte, jose.HS256, []byte(keySecret),
jose.Header("cty", "twilio-fpa;v=1"),
jose.Header("typ", "JWT"),
jose.Header("alg", "HS256"),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(token)
}

Related

JWT Claims not retained after token signing

I have the following code. I am creating a json web token (using golang-jwt) with custom claims. The issue is that when I sign the token with a key (method = HS256) and then parse the token the claims are getting changed. What mistake I am making.
Code:
package main
import (
"fmt"
"time"
"github.com/golang-jwt/jwt/v4"
)
type MyCustomClaims struct {
userid int
jwt.RegisteredClaims
}
func (app *Config) generateJWT(userid int) {
//Code to generate jwt
jt := jwt.NewWithClaims(jwt.SigningMethodHS256, MyCustomClaims{
userid,
jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(3 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
},
})
fmt.Println("What was put", jt.Claims.(MyCustomClaims).userid)
token, _ := jt.SignedString(app.secret)
//Code to check whether claims are retained
parsed_token, _ := jwt.ParseWithClaims(token, &MyCustomClaims{}, func(t *jwt.Token) (interface{}, error) {
return app.secret, nil
})
fmt.Println("What was parsed", parsed_token.Claims.(*MyCustomClaims).userid)
}
Output
What was put 8
What was parsed 0
You have to export the userid field (make it start with a capital letter). Unexported fields cannot be JSON encoded.
type MyCustomClaims struct {
UserID int `json:"userid"`
jwt.RegisteredClaims
}

Preloading 'belongs to' associations both ways

I'd like to use GORM's 'belongs to' association in a way similar to Django's one-to-one relationships. Consider the following example in which each User is associated with one Profile:
package main
import (
"fmt"
"os"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/sirupsen/logrus"
)
type User struct {
gorm.Model
Name string
}
func (user User) String() string {
return fmt.Sprintf("User(Name=%s)", user.Name)
}
type Profile struct {
gorm.Model
UserID uint
User User
Name string
}
func (profile Profile) String() string {
return fmt.Sprintf("Profile(Name=%s, User=%d)", profile.Name, profile.UserID)
}
func (user *User) AfterCreate(scope *gorm.Scope) error {
profile := Profile{
UserID: user.ID,
Name: user.Name,
}
return scope.DB().Create(&profile).Error
}
const dbName = "examplegorm.db"
func main() {
db, err := gorm.Open("sqlite3", dbName)
if err != nil {
logrus.Fatalf("open db: %v", err)
}
defer func() {
db.Close()
os.Remove(dbName)
}()
db.LogMode(true)
db.AutoMigrate(&User{})
db.AutoMigrate(&Profile{})
user := User{Name: "jinzhu"}
if err := db.Create(&user).Error; err != nil {
logrus.Fatalf("create user: %v", err)
}
var profile Profile
if err := db.Where(Profile{UserID: user.ID}).Preload("User").First(&profile).Error; err != nil {
logrus.Fatalf("get profile: %v", err)
}
logrus.Infof("profile: %v", profile)
logrus.Infof("user: %v", profile.User)
}
In this example, I query for a Profile and preload its User. I would actually like to do this the other way, however: query a User and preload its Profile.
As I understand it, in Django you would be able to access both the profile.user and the user.profile, but if I try to add Profile and ProfileID fields to the User model,
type User struct {
gorm.Model
Name string
Profile
ProfileID uint
}
I get an 'invalid recursive type' error:
# command-line-arguments
./gorm_belongs_to.go:23:6: invalid recursive type Profile
Is there any way to get a user.Profile in this GORM example?
I think that the problem in your case is using the name Profile which is the same as the type.
If your User struct will look something like this it should work:
type User struct {
gorm.Model
Name string
UserProfile Profile
UserProfileID uint
}

How to create certificate with undefined validity period

If I omit the attribute NotAfter during initialisation of an x509.Certificate, it results in the expiry date being set to "0001-01-01", thus making the certificate expired.
In PHP + phpseclib, I can skip setting this field, making the issued certificate never expire. Is it possible to do this in Go?
RFC 5280 states:
4.1.2.5. Validity To indicate that a certificate has no well-defined expiration date, the notAfter SHOULD be assigned the GeneralizedTime value of 99991231235959Z.
How can I do this in Go?
TL;DR: Neither NotBefore nor NotAfter is optional. You must be mistaken about your Python PHP script. I would assume it uses some kind of default value for NotAfter if you don't specify it.
crypto/x509 defines the Validity as follows:
type validity struct {
NotBefore, NotAfter time.Time
}
Since neither field is a pointer, they cannot be undefined.
If you want to force the issue, you can use a modified copy of the x509 types to encode a certificate without the NotAfter field, but the result is unusable. Playground link
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"log"
"math/big"
"os"
"time"
)
// copy of x509.certificate, with TBSCertificate.Validity.NotAfter omitted
type certificate struct {
TBSCertificate struct {
Version int `asn1:"optional,explicit,default:0,tag:0"`
SerialNumber *big.Int
SignatureAlgorithm pkix.AlgorithmIdentifier
Issuer asn1.RawValue
Validity struct {
NotBefore time.Time
}
Subject asn1.RawValue
PublicKey struct {
Raw asn1.RawContent
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
UniqueId asn1.BitString `asn1:"optional,tag:1"`
SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"`
Extensions []pkix.Extension `asn1:"optional,explicit,tag:3"`
}
SignatureAlgorithm pkix.AlgorithmIdentifier
SignatureValue asn1.BitString
}
func main() {
derBytes := generateSelfSigned()
// re-marshal to remove the NotAfter field
var c certificate
_, err := asn1.Unmarshal(derBytes, &c)
check(err)
derBytes, err = asn1.Marshal(c)
check(err)
pem.Encode(os.Stdout, &pem.Block{
Type: "CERTIFICATE",
Bytes: derBytes,
})
}
func generateSelfSigned() (derBytes []byte) {
pk, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
check(err)
tpl := &x509.Certificate{SerialNumber: big.NewInt(1)}
derBytes, err = x509.CreateCertificate(rand.Reader, tpl, tpl, &pk.PublicKey, pk)
check(err)
return derBytes
}
func check(err error) {
if err != nil {
log.Fatal(err)
}
}
If you hand one of these certificates to openssl, for instance, parsing fails as expected with
unable to load certificate
139990566643520:error:0D078079:asn1 encoding routines:asn1_item_embed_d2i:field missing:crypto/asn1/tasn_dec.c:389:Field=notAfter, Type=X509_VAL

POST file and nested params golang

I'm already posting a file and some params, but now I need to send nested params with a struct and I don't know where to use that (I'm new in Go).
This is what I have: https://play.golang.org/p/L4qx6AZhUO
Now, I'm creating this structs:
type S3 struct {
Accesskeyid string
Secretaccesskey string
Bucket string
}
type Test struct {
Outputformat string
Wait string
Output S3
File []byte
}
And I would like to send the Test struct WITH the file. Any ideas?
Thanks!
Okay, So given what you've told me and what little information I have with your example, I might do something like this.
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
type S3 struct {
Accesskeyid string
Secretaccesskey string
Bucket string
}
type Test struct {
Outputformat string
Wait string
Output S3
File []byte
}
func main() {
myStrut := Test{
Outputformat: "Json",
Wait: "Some Time",
Output: S3{
Accesskeyid: "my id",
Secretaccesskey: "secret id",
Bucket: "east",
},
File: []byte(`some bytes`),
}
jsonValue, err := json.Marshal(myStrut)
if err != nil {
panic(err)
}
fmt.Printf("Test showing that data was marshalled\n %q\n", jsonValue)
resp, err := http.Post("some url", "application/json", bytes.NewBuffer(jsonValue))
if err != nil {
panic(err)
}
fmt.Println(resp.Status)
}
Now from what i gleamed in the comments you might be also having trouble opening the file as a byte array to assign to your struct. Here's an example you can use you help you open the file as a byte array so that you can assign those bytes to your struct.
package main
import (
"fmt"
"io/ioutil"
)
func main() {
//An example of how to open a file and turn it into bytes for your struct
byteArray, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
fmt.Println(byteArray)
}

unsupported protocol scheme while creating ec2 Security group

I am trying to create security group using goamz.
Below is my code.
package main
import (
"fmt"
"os"
"github.com/mitchellh/goamz/aws"
"github.com/mitchellh/goamz/ec2"
)
type SecurityGroup struct {
Id string `xml:"groupId"`
Name string `xml:"groupName"`
Description string `xml:"groupDescription"`
VpcId string `xml:"vpcId"`
}
func main() {
auth := aws.Auth{
AccessKey: os.Getenv("key"),
SecretKey: os.Getenv("secret"),
}
region := aws.Region{
Name : "us-east-1",
}
ec2conn := ec2.New(auth, region)
fmt.Printf("%+v\n", ec2conn)
resp, err := ec2conn.CreateSecurityGroup(ec2.SecurityGroup{Name: "testing12",
Description: "testing123", VpcId: "vpc-123456"})
fmt.Printf("%+v\n", resp)
if err != nil {
fmt.Printf("%s\n", err.Error())
}
}
And I get the below Response upon execution.
<nil>
Get /? XXXXXXXXX
unsupported protocol scheme ""
I am not sure whether we use any protocol explicitly to create.
Please help me understanding this.

Resources