From bea301dd062128bd84d077fc4e741b2caf0ccdfc Mon Sep 17 00:00:00 2001 From: Alvin Rizki <4lvin.rizki@gmail.com> Date: Sat, 2 Nov 2019 23:50:16 +0700 Subject: [PATCH 1/2] add token checking expiration checking --- jwt.go | 20 ++++++++++++++++++++ smooch.go | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/jwt.go b/jwt.go index f8a33a8..79f1b44 100644 --- a/jwt.go +++ b/jwt.go @@ -16,3 +16,23 @@ func GenerateJWT(scope string, keyID string, secret string) (string, error) { return token.SignedString([]byte(secret)) } + +// isJWTExpired will check whether Smooch JWT is expired or not. +func isJWTExpired(jwtToken string, secret string) (bool, error) { + _, err := jwt.ParseWithClaims(jwtToken, jwt.MapClaims{}, func(t *jwt.Token) (interface{}, error) { + return []byte(secret), nil + }) + + if err == nil { + return false, nil + } + + switch err.(type) { + case *jwt.ValidationError: + vErr := err.(*jwt.ValidationError) + if vErr.Errors == jwt.ValidationErrorExpired { + return true, nil + } + } + return false, err +} diff --git a/smooch.go b/smooch.go index f531871..5dc224c 100644 --- a/smooch.go +++ b/smooch.go @@ -17,6 +17,8 @@ import ( var ( ErrUserIDEmpty = errors.New("user id is empty") + ErrKeyIDEmpty = errors.New("key id is empty") + ErrSecretEmpty = errors.New("secret is empty") ErrMessageNil = errors.New("message is nil") ErrMessageRoleEmpty = errors.New("message.Role is empty") ErrMessageTypeEmpty = errors.New("message.Type is empty") @@ -52,6 +54,7 @@ type WebhookEventHandler func(payload *Payload) type Client interface { Handler() http.Handler + IsJWTExpired() (bool, error) AddWebhookEventHandler(handler WebhookEventHandler) Send(userID string, message *Message) (*ResponsePayload, error) VerifyRequest(r *http.Request) bool @@ -63,6 +66,8 @@ type Client interface { type smoochClient struct { mux *http.ServeMux appID string + keyID string + secret string jwtToken string verifySecret string logger Logger @@ -72,6 +77,14 @@ type smoochClient struct { } func New(o Options) (*smoochClient, error) { + if o.KeyID == "" { + return nil, ErrKeyIDEmpty + } + + if o.Secret == "" { + return nil, ErrSecretEmpty + } + if o.VerifySecret == "" { return nil, ErrVerifySecretEmpty } @@ -109,6 +122,8 @@ func New(o Options) (*smoochClient, error) { sc := &smoochClient{ mux: o.Mux, appID: o.AppID, + keyID: o.KeyID, + secret: o.Secret, verifySecret: o.VerifySecret, logger: o.Logger, region: region, @@ -124,6 +139,11 @@ func (sc *smoochClient) Handler() http.Handler { return sc.mux } +// IsJWTExpired will check whether Smooch JWT is expired or not. +func (sc *smoochClient) IsJWTExpired() (bool, error) { + return isJWTExpired(sc.jwtToken, sc.secret) +} + func (sc *smoochClient) AddWebhookEventHandler(handler WebhookEventHandler) { sc.webhookEventHandlers = append(sc.webhookEventHandlers, handler) } From 0f402017863a33fa53ed1ce624c54d0327e18fc6 Mon Sep 17 00:00:00 2001 From: Alvin Rizki <4lvin.rizki@gmail.com> Date: Sun, 3 Nov 2019 00:01:11 +0700 Subject: [PATCH 2/2] add RenewToken() --- smooch.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/smooch.go b/smooch.go index 5dc224c..4fe2276 100644 --- a/smooch.go +++ b/smooch.go @@ -13,6 +13,7 @@ import ( "os" "path" "strings" + "sync" ) var ( @@ -55,6 +56,7 @@ type WebhookEventHandler func(payload *Payload) type Client interface { Handler() http.Handler IsJWTExpired() (bool, error) + RenewToken() (string, error) AddWebhookEventHandler(handler WebhookEventHandler) Send(userID string, message *Message) (*ResponsePayload, error) VerifyRequest(r *http.Request) bool @@ -74,6 +76,7 @@ type smoochClient struct { region string webhookEventHandlers []WebhookEventHandler httpClient *http.Client + mtx sync.Mutex } func New(o Options) (*smoochClient, error) { @@ -144,6 +147,20 @@ func (sc *smoochClient) IsJWTExpired() (bool, error) { return isJWTExpired(sc.jwtToken, sc.secret) } +// RenewToken will generate new Smooch JWT token. +func (sc *smoochClient) RenewToken() (string, error) { + sc.mtx.Lock() + defer sc.mtx.Unlock() + + jwtToken, err := GenerateJWT("app", sc.keyID, sc.secret) + if err != nil { + return "", err + } + + sc.jwtToken = jwtToken + return jwtToken, nil +} + func (sc *smoochClient) AddWebhookEventHandler(handler WebhookEventHandler) { sc.webhookEventHandlers = append(sc.webhookEventHandlers, handler) }