oktopus/backend/services/acs/internal/auth/auth.go
2024-04-20 11:20:38 -03:00

113 lines
2.9 KiB
Go

package auth
import (
"crypto/md5"
"crypto/rand"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"strings"
)
type myjar struct {
jar map[string][]*http.Cookie
}
func (p *myjar) SetCookies(u *url.URL, cookies []*http.Cookie) {
p.jar[u.Host] = cookies
}
func (p *myjar) Cookies(u *url.URL) []*http.Cookie {
return p.jar[u.Host]
}
func Auth(username string, password string, uri string) (bool, error) {
client := &http.Client{}
jar := &myjar{}
jar.jar = make(map[string][]*http.Cookie)
client.Jar = jar
var req *http.Request
var resp *http.Response
var err error
req, err = http.NewRequest("GET", uri, nil)
resp, err = client.Do(req)
if err != nil {
return false, err
}
// if resp.StatusCode == 401 {
// var authorization map[string]string = DigestAuthParams(resp)
// realmHeader := authorization["realm"]
// qopHeader := authorization["qop"]
// nonceHeader := authorization["nonce"]
// opaqueHeader := authorization["opaque"]
// realm := realmHeader
// // A1
// h := md5.New()
// A1 := fmt.Sprintf("%s:%s:%s", username, realm, password)
// io.WriteString(h, A1)
// HA1 := fmt.Sprintf("%x", h.Sum(nil))
// // A2
// h = md5.New()
// A2 := fmt.Sprintf("GET:%s", "/auth")
// io.WriteString(h, A2)
// HA2 := fmt.Sprintf("%x", h.Sum(nil))
// // response
// cnonce := RandomKey()
// response := H(strings.Join([]string{HA1, nonceHeader, "00000001", cnonce, qopHeader, HA2}, ":"))
// // now make header
// AuthHeader := fmt.Sprintf(`Digest username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=00000001, qop=%s, response="%s", opaque="%s", algorithm=MD5`,
// username, realmHeader, nonceHeader, "/auth", cnonce, qopHeader, response, opaqueHeader)
// req.Header.Set("Authorization", AuthHeader)
// resp, err = client.Do(req)
// } else {
// return false, fmt.Errorf("response status code should have been 401, it was %v", resp.StatusCode)
// }
return resp.StatusCode == 200, err
}
/*
Parse Authorization header from the http.Request. Returns a map of
auth parameters or nil if the header is not a valid parsable Digest
auth header.
*/
func DigestAuthParams(r *http.Response) map[string]string {
s := strings.SplitN(r.Header.Get("Www-Authenticate"), " ", 2)
if len(s) != 2 || s[0] != "Digest" {
return nil
}
result := map[string]string{}
for _, kv := range strings.Split(s[1], ",") {
parts := strings.SplitN(kv, "=", 2)
if len(parts) != 2 {
continue
}
result[strings.Trim(parts[0], "\" ")] = strings.Trim(parts[1], "\" ")
}
return result
}
func RandomKey() string {
k := make([]byte, 12)
for bytes := 0; bytes < len(k); {
n, err := rand.Read(k[bytes:])
if err != nil {
panic("rand.Read() failed")
}
bytes += n
}
return base64.StdEncoding.EncodeToString(k)
}
/*
H function for MD5 algorithm (returns a lower-case hex MD5 digest)
*/
func H(data string) string {
digest := md5.New()
digest.Write([]byte(data))
return fmt.Sprintf("%x", digest.Sum(nil))
}