Skip to content

Commit

Permalink
Merge pull request #27 from mynaparrot/auth_rewrite
Browse files Browse the repository at this point in the history
Auth rewrite
  • Loading branch information
jibon57 authored May 10, 2022
2 parents b9f6bbe + b307c47 commit 5577a02
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 14 deletions.
2 changes: 1 addition & 1 deletion config_sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ livekit_info:
api_key: "APIiYAA5w37Cfo2"
secret: "6aNur7qqupeZhFYNOJVUyeXxXhVw8f4lm13pEDUx8SgB"
# value in minutes. Default 10 minutes. Client will renew token automatically
token_validity: 2h
token_validity: 10m
redis_info:
host: redis
port: "6379"
Expand Down
51 changes: 47 additions & 4 deletions internal/controllers/auth_token.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package controllers

import (
"encoding/json"
"github.com/gofiber/fiber/v2"
"github.com/livekit/protocol/auth"
"github.com/mynaparrot/plugNmeet/internal/config"
"github.com/mynaparrot/plugNmeet/internal/models"
"strings"
Expand Down Expand Up @@ -98,6 +100,35 @@ func HandleVerifyToken(c *fiber.Ctx) error {
})
}

cm := c.Locals("claims")
// after usage, we can make it null
// as we don't need this value again.
c.Locals("claims", nil)

claims := new(auth.ClaimGrants)
err = json.Unmarshal([]byte(cm.(string)), claims)

if err != nil {
return c.JSON(fiber.Map{
"status": false,
"msg": err.Error(),
})
}

// if user id isn't string then will have problem
// so, we'll set it again here
claims.Identity = requestedUserId.(string)
claims.Video.Room = roomId.(string)

au := models.NewAuthTokenModel()
token, err := au.GenerateLivekitToken(claims)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"msg": err.Error(),
})
}

// if nil then assume production
if req.IsProduction == nil {
b := new(bool)
Expand All @@ -109,6 +140,7 @@ func HandleVerifyToken(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": true,
"msg": "token is valid",
"token": token,
})
}

Expand All @@ -123,6 +155,7 @@ func HandleVerifyToken(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"status": status,
"msg": msg,
"token": token,
})
}

Expand All @@ -148,7 +181,7 @@ func HandleVerifyHeaderToken(c *fiber.Ctx) error {
Token: authToken,
}

claims, err := m.DoValidateToken(info)
claims, err := m.DoValidateToken(info, false)
if err != nil {
_ = c.SendStatus(errStatus)
return c.JSON(fiber.Map{
Expand All @@ -157,13 +190,23 @@ func HandleVerifyHeaderToken(c *fiber.Ctx) error {
})
}

// TO-DO verify if meeting is running or not.
// If not running then we'll send error response.
// new livekit server won't allow creat room by join.
// we only need this during verify token
// because it will return livekit token, if success
if strings.Contains(c.Path(), "verifyToken") {
j, err := json.Marshal(claims)
if err != nil {
return c.JSON(fiber.Map{
"status": false,
"msg": err.Error(),
})
}
c.Locals("claims", string(j))
}

c.Locals("isAdmin", claims.Video.RoomAdmin)
c.Locals("roomId", claims.Video.Room)
c.Locals("requestedUserId", claims.Identity)

return c.Next()
}

Expand Down
6 changes: 4 additions & 2 deletions internal/controllers/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ func HandleWebhook(c *fiber.Ctx) error {
}
m := models.NewAuthTokenModel()

claims, err := m.DoValidateToken(req)
// here request is coming from livekit
// so, we'll use livekit secret to validate
claims, err := m.DoValidateToken(req, true)
if err != nil {
return c.SendStatus(fiber.StatusForbidden)
}
Expand All @@ -47,4 +49,4 @@ func HandleWebhook(c *fiber.Ctx) error {
models.NewWebhookModel(event)

return c.SendStatus(fiber.StatusOK)
}
}
2 changes: 1 addition & 1 deletion internal/controllers/websocket_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (c *websocketController) validation() bool {
Token: c.token,
}

claims, err := m.DoValidateToken(info)
claims, err := m.DoValidateToken(info, false)
if err != nil {
err = c.kws.EmitTo(c.kws.UUID, []byte("invalid token"))
if err == nil {
Expand Down
39 changes: 33 additions & 6 deletions internal/models/auth_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (a *authTokenModel) DoGenerateToken(g *GenTokenReq) (string, error) {
return "", err
}

at := auth.NewAccessToken(a.app.LivekitInfo.ApiKey, a.app.LivekitInfo.Secret)
at := auth.NewAccessToken(a.app.Client.ApiKey, a.app.Client.Secret)
grant := &auth.VideoGrant{
RoomJoin: true,
Room: g.RoomId,
Expand All @@ -81,6 +81,27 @@ func (a *authTokenModel) DoGenerateToken(g *GenTokenReq) (string, error) {
return at.ToJWT()
}

// GenerateLivekitToken will generate token to join livekit server
// It will use info as other validation. We just don't want user simple copy/past token from url
// instated plugNmeet-server will generate once validation will be completed.
func (a *authTokenModel) GenerateLivekitToken(claims *auth.ClaimGrants) (string, error) {
at := auth.NewAccessToken(a.app.LivekitInfo.ApiKey, a.app.LivekitInfo.Secret)
grant := &auth.VideoGrant{
RoomJoin: true,
Room: claims.Video.Room,
RoomAdmin: claims.Video.RoomAdmin,
Hidden: claims.Video.Hidden,
}

at.AddGrant(grant).
SetIdentity(claims.Identity).
SetName(claims.Name).
SetMetadata(claims.Metadata).
SetValidFor(a.app.LivekitInfo.TokenValidity)

return at.ToJWT()
}

func (a *authTokenModel) assignLockSettings(g *GenTokenReq) *LockSettings {
l := new(LockSettings)
ul := g.UserInfo.UserMetadata.LockSettings
Expand Down Expand Up @@ -174,7 +195,7 @@ func (a *authTokenModel) makePresenter(g *GenTokenReq) {
// Because we don't want to add any service settings which may
// prevent to work recorder/rtmp bot as expected.
func (a *authTokenModel) GenTokenForRecorder(g *GenTokenReq) (string, error) {
at := auth.NewAccessToken(a.app.LivekitInfo.ApiKey, a.app.LivekitInfo.Secret)
at := auth.NewAccessToken(a.app.Client.ApiKey, a.app.Client.Secret)
// basic permission
grant := &auth.VideoGrant{
RoomJoin: true,
Expand All @@ -201,13 +222,19 @@ type ValidateTokenReq struct {
grant *auth.APIKeyTokenVerifier
}

func (a *authTokenModel) DoValidateToken(v *ValidateTokenReq) (*auth.ClaimGrants, error) {
// DoValidateToken can be use to validate both livekit & plugnmeet token
func (a *authTokenModel) DoValidateToken(v *ValidateTokenReq, livekit bool) (*auth.ClaimGrants, error) {
grant, err := auth.ParseAPIToken(v.Token)
if err != nil {
return nil, err
}

claims, err := grant.Verify(a.app.LivekitInfo.Secret)
secret := a.app.Client.Secret
if livekit {
secret = a.app.LivekitInfo.Secret
}

claims, err := grant.Verify(secret)
if err != nil {
return nil, err
}
Expand All @@ -217,7 +244,7 @@ func (a *authTokenModel) DoValidateToken(v *ValidateTokenReq) (*auth.ClaimGrants
}

func (a *authTokenModel) verifyTokenWithRoomInfo(v *ValidateTokenReq) (*auth.ClaimGrants, *RoomInfo, error) {
claims, err := a.DoValidateToken(v)
claims, err := a.DoValidateToken(v, false)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -249,7 +276,7 @@ func (a *authTokenModel) DoRenewToken(v *ValidateTokenReq) (string, error) {
return "", err
}

at := auth.NewAccessToken(a.app.LivekitInfo.ApiKey, a.app.LivekitInfo.Secret)
at := auth.NewAccessToken(a.app.Client.ApiKey, a.app.Client.Secret)

at.AddGrant(claims.Video).
SetIdentity(claims.Identity).
Expand Down

0 comments on commit 5577a02

Please sign in to comment.