parent
531c267473
commit
88c59ac00b
|
@ -25,6 +25,7 @@ require (
|
|||
github.com/go-playground/locales v0.13.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.17.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang/protobuf v1.4.3 // indirect
|
||||
github.com/gorilla/context v1.1.1 // indirect
|
||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||
|
|
|
@ -123,6 +123,8 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG
|
|||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
var VERSION = "development"
|
||||
|
||||
type configData struct {
|
||||
JWTSecret JWTSecret `toml"jwt_secret"`
|
||||
EndpointURL string `toml:"endpoint_url"`
|
||||
XMPP XMPPService `toml:"xmpp"`
|
||||
Webserver web.Service `toml:"webserver"`
|
||||
|
@ -42,6 +43,7 @@ func main() {
|
|||
}
|
||||
// just for more beautiful config file - jere
|
||||
config.XMPP.EndpointURL = config.EndpointURL
|
||||
config.XMPP.JWTSecret = config.JWTSecret
|
||||
|
||||
go func() {
|
||||
if err := config.XMPP.Run(); err != nil {
|
||||
|
@ -49,7 +51,7 @@ func main() {
|
|||
}
|
||||
}()
|
||||
|
||||
config.Webserver.ModuleRegister(Bind(&config.XMPP))
|
||||
config.Webserver.ModuleRegister(Bind(&config.XMPP, config.JWTSecret))
|
||||
|
||||
log.Info("startup")
|
||||
if err := config.Webserver.Run(); err != nil {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/golang-jwt/jwt"
|
||||
"mellium.im/xmpp/jid"
|
||||
)
|
||||
|
||||
// JWTSecret the secret
|
||||
type JWTSecret string
|
||||
|
||||
// JWTToken data field
|
||||
type JWTToken struct {
|
||||
jwt.StandardClaims
|
||||
Token string `json:"token"`
|
||||
JID string `json:"jid"`
|
||||
}
|
||||
|
||||
// Generate an jwt token by token and jid
|
||||
func (s JWTSecret) Generate(jid jid.JID, token string) (string, error) {
|
||||
jwtToken := JWTToken{
|
||||
Token: token,
|
||||
JID: jid.String(),
|
||||
}
|
||||
claim := jwt.NewWithClaims(jwt.SigningMethodHS512, jwtToken)
|
||||
t, err := claim.SignedString([]byte(s))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// Read token to token and jid
|
||||
func (s JWTSecret) Read(jwtToken string) (jid.JID, string, error) {
|
||||
token, err := jwt.ParseWithClaims(jwtToken, &JWTToken{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(s), nil
|
||||
})
|
||||
if err != nil {
|
||||
return jid.JID{}, "", err
|
||||
}
|
||||
claims, ok := token.Claims.(*JWTToken)
|
||||
if !ok {
|
||||
return jid.JID{}, "", jwt.ErrInvalidKey
|
||||
}
|
||||
addr, err := jid.Parse(claims.JID)
|
||||
if err != nil {
|
||||
return jid.JID{}, "", err
|
||||
}
|
||||
return addr, claims.Token, nil
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"mellium.im/xmpp/jid"
|
||||
)
|
||||
|
||||
func TestJWT(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
addr := "a@example.org"
|
||||
token := "pushtoken"
|
||||
|
||||
secret := JWTSecret("CHANGEME")
|
||||
jwt, err := secret.Generate(jid.MustParse(addr), token)
|
||||
assert.NoError(err)
|
||||
assert.NoEqual("", jwt)
|
||||
|
||||
jid, t, err := secret.Read(jwt)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, jid.String())
|
||||
assert.Equal(t, token)
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"dev.sum7.eu/genofire/golang-lib/web"
|
||||
"dev.sum7.eu/genofire/golang-lib/web/api/status"
|
||||
"dev.sum7.eu/genofire/golang-lib/web/metrics"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Bind to webservice
|
||||
|
@ -18,13 +18,13 @@ import (
|
|||
// @securityDefinitions.apikey ApiKeyAuth
|
||||
// @in header
|
||||
// @name Authorization
|
||||
func Bind(xmpp *XMPPService) web.ModuleRegisterFunc {
|
||||
func Bind(xmpp *XMPPService, jwt JWTSecret) web.ModuleRegisterFunc {
|
||||
return func(r *gin.Engine, ws *web.Service) {
|
||||
// docs.Bind(r, ws)
|
||||
|
||||
status.Register(r, ws)
|
||||
metrics.Register(r, ws)
|
||||
Get(r, ws)
|
||||
Post(r, ws, xmpp)
|
||||
Post(r, ws, xmpp, jwt)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,16 +2,22 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"dev.sum7.eu/genofire/golang-lib/web"
|
||||
)
|
||||
|
||||
func Post(r *gin.Engine, ws *web.Service, xmpp *XMPPService) {
|
||||
func Post(r *gin.Engine, ws *web.Service, xmpp *XMPPService, jwtsecret JWTSecret) {
|
||||
r.POST("/UP", func(c *gin.Context) {
|
||||
to := c.Query("to")
|
||||
token := c.Query("token")
|
||||
to, token, err := jwtsecret.Read(c.Query("token"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, web.HTTPError{
|
||||
Message: "jwt token unauthoried - or not given",
|
||||
Error: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
b, err := ioutil.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, web.HTTPError{
|
||||
|
|
|
@ -23,6 +23,7 @@ type XMPPService struct {
|
|||
Secret string `toml:"secret"`
|
||||
// hidden here for beautiful config file
|
||||
EndpointURL string `toml:"-"`
|
||||
JWTSecret JWTSecret `toml"-"`
|
||||
session *xmpp.Session
|
||||
}
|
||||
|
||||
|
@ -102,7 +103,13 @@ func (s *XMPPService) handleRegister(iq stanza.IQ, t xmlstream.TokenReadEncoder,
|
|||
reply.Register.Error = &messages.ErrorData{Body: "no token"}
|
||||
return nil
|
||||
}
|
||||
endpoint := s.EndpointURL+"/UP?token=" + token + "&to=" + iq.From.String()
|
||||
jwt, err := s.JWTSecret.Generate(iq.From, token)
|
||||
if err != nil {
|
||||
log.Errorf("unable jwt generation: %v", err)
|
||||
reply.Register.Error = &messages.ErrorData{Body: "jwt error on gateway"}
|
||||
return nil
|
||||
}
|
||||
endpoint := s.EndpointURL + "/UP?token=" + jwt
|
||||
reply.IQ.Type = stanza.ResultIQ
|
||||
reply.Register.Endpoint = &messages.EndpointData{Body: endpoint}
|
||||
log.Infof("generate respone: %v", endpoint)
|
||||
|
@ -145,14 +152,14 @@ func (s *XMPPService) handleDisco(iq stanza.IQ, t xmlstream.TokenReadEncoder, st
|
|||
}
|
||||
|
||||
// SendMessage of an UP Notification
|
||||
func (s *XMPPService) SendMessage(to, token, content string) error {
|
||||
func (s *XMPPService) SendMessage(to jid.JID, token, content string) error {
|
||||
log.WithFields(map[string]interface{}{
|
||||
"to": to,
|
||||
"token": token,
|
||||
}).Info("forward message to xmpp")
|
||||
return s.session.Encode(context.TODO(), messages.Message{
|
||||
Message: stanza.Message{
|
||||
To: jid.MustParse(to),
|
||||
To: to,
|
||||
From: jid.MustParse(s.JID),
|
||||
// Type: stanza.ChatMessage,
|
||||
Type: stanza.NormalMessage,
|
||||
|
|
Loading…
Reference in New Issue