package middleware import ( "net/url" "strings" "github.com/gin-gonic/gin" "github.com/pikami/cosmium/api/config" "github.com/pikami/cosmium/internal/authentication" "github.com/pikami/cosmium/internal/logger" ) func Authentication() gin.HandlerFunc { return func(c *gin.Context) { requestUrl := c.Request.URL.String() if config.Config.DisableAuth || strings.HasPrefix(requestUrl, "/_explorer") || strings.HasPrefix(requestUrl, "/cosmium") { return } resourceType := urlToResourceType(requestUrl) resourceId := requestToResourceId(c) authHeader := c.Request.Header.Get("authorization") date := c.Request.Header.Get("x-ms-date") expectedSignature := authentication.GenerateSignature( c.Request.Method, resourceType, resourceId, date, config.Config.AccountKey) decoded, _ := url.QueryUnescape(authHeader) params, _ := url.ParseQuery(decoded) clientSignature := strings.Replace(params.Get("sig"), " ", "+", -1) if clientSignature != expectedSignature { logger.Errorf("Got wrong signature from client.\n- Expected: %s\n- Got: %s\n", expectedSignature, clientSignature) c.IndentedJSON(401, gin.H{ "code": "Unauthorized", "message": "Wrong signature.", }) c.Abort() } } } func urlToResourceType(requestUrl string) string { var resourceType string parts := strings.Split(requestUrl, "/") switch len(parts) { case 2, 3: resourceType = parts[1] case 4, 5: resourceType = parts[3] case 6, 7: resourceType = parts[5] } return resourceType } func requestToResourceId(c *gin.Context) string { databaseId, _ := c.Params.Get("databaseId") collId, _ := c.Params.Get("collId") docId, _ := c.Params.Get("docId") resourceType := urlToResourceType(c.Request.URL.String()) var resourceId string if databaseId != "" { resourceId += "dbs/" + databaseId } if collId != "" { resourceId += "/colls/" + collId } if docId != "" { resourceId += "/docs/" + docId } isFeed := c.Request.Header.Get("A-Im") == "Incremental Feed" if resourceType == "pkranges" && isFeed { resourceId = collId } return resourceId }