79 lines
1.8 KiB
Go
79 lines
1.8 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"local/dndex/config"
|
|
"local/dndex/storage"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func Verify(g storage.RateLimitedGraph, w http.ResponseWriter, r *http.Request) error {
|
|
token, ok := getToken(r)
|
|
if !ok {
|
|
return errors.New("auth not found")
|
|
}
|
|
if !config.New().Auth {
|
|
return nil
|
|
}
|
|
if isPublic(token, g, r) {
|
|
return nil
|
|
}
|
|
return verifyToken(token, g, r)
|
|
}
|
|
|
|
func getToken(r *http.Request) (Token, bool) {
|
|
if !config.New().Auth {
|
|
namespaces, ok := r.URL.Query()["ns"]
|
|
if ok && len(namespaces) > 0 {
|
|
return Token{Namespace: namespaces[0], ID: uuid.New().String()}, true
|
|
}
|
|
}
|
|
cookie, err := r.Cookie(AuthKey)
|
|
if err != nil {
|
|
return Token{}, false
|
|
}
|
|
obfuscated := cookie.Value
|
|
var token Token
|
|
err = token.Deobfuscate(obfuscated)
|
|
return token, err == nil
|
|
}
|
|
|
|
func isPublic(token Token, g storage.RateLimitedGraph, r *http.Request) bool {
|
|
return isPublicNamespace(r.Context(), g, token.Namespace)
|
|
}
|
|
|
|
func isPublicNamespace(ctx context.Context, g storage.RateLimitedGraph, namespace string) bool {
|
|
maybePublicContainer, err := g.Get(ctx, toAuthNamespace(namespace), UserKey)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return maybePublicContainer.Title == ""
|
|
}
|
|
|
|
func verifyToken(token Token, g storage.RateLimitedGraph, r *http.Request) error {
|
|
serverTokenContainer, err := g.Get(r.Context(), toAuthNamespace(token.Namespace), token.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var serverToken Token
|
|
if err := serverToken.Deobfuscate(serverTokenContainer.Title); err != nil {
|
|
return err
|
|
}
|
|
|
|
if token.Namespace != serverToken.Namespace {
|
|
return errors.New("token namespace does not match request's namespace")
|
|
}
|
|
|
|
modified := time.Unix(0, serverTokenContainer.Modified)
|
|
if time.Since(modified) > config.New().AuthLifetime {
|
|
return errors.New("token is expired")
|
|
}
|
|
|
|
return nil
|
|
}
|