Files
ipe/auth.go
T
2015-01-02 18:20:27 -03:00

89 lines
2.3 KiB
Go

// Copyright 2014 Claudemiro Alves Feitosa Neto. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"github.com/gorilla/mux"
"net/http"
"net/url"
"sort"
"strings"
)
// Calculate the Mac
func HashMAC(message, key []byte) string {
mac := hmac.New(sha256.New, key)
mac.Write(message)
expectedMAC := mac.Sum(nil)
return hex.EncodeToString(expectedMAC)
}
// Verify the message
func checkMAC(message, messageMAC, key []byte) bool {
return string(messageMAC) == HashMAC(message, key)
}
// Prepare Querystring
func prepareQueryString(params url.Values) string {
var keys []string
for key := range params {
keys = append(keys, strings.ToLower(key))
}
sort.Strings(keys)
var pieces []string
for _, key := range keys {
pieces = append(pieces, key+"="+params.Get(key))
}
return strings.Join(pieces, "&")
}
// Authenticate pusher
// see: https://gist.github.com/mloughran/376898
//
// The signature is a HMAC SHA256 hex digest.
// This is generated by signing a string made up of the following components concatenated with newline characters \n.
//
// * The uppercase request method (e.g. POST)
// * The request path (e.g. /some/resource)
// * The query parameters sorted by key, with keys converted to lowercase, then joined as in the query string.
// Note that the string must not be url escaped (e.g. given the keys auth_key: foo, Name: Something else, you get auth_key=foo&name=Something else)
func RestAuthenticationHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
appID := vars["app_id"]
currentApp, err := Conf.GetAppByAppID(appID)
if err != nil {
http.Error(w, "Not authorized", http.StatusUnauthorized)
return
}
params := r.URL.Query()
authSignature := params.Get("auth_signature")
params.Del("auth_signature")
queryString := prepareQueryString(params)
toSign := strings.ToUpper(r.Method) + "\n" + r.URL.Path + "\n" + queryString
if checkMAC([]byte(toSign), []byte(authSignature), []byte(currentApp.Secret)) {
h.ServeHTTP(w, r)
} else {
http.Error(w, "Not authorized", http.StatusUnauthorized)
}
})
}