package oidc import ( "crypto/rand" "encoding/base64" "errors" "fmt" "net" "net/http" "net/url" "strings" "time" "github.com/coreos/go-oidc/jose" ) // RequestTokenExtractor funcs extract a raw encoded token from a request. type RequestTokenExtractor func(r *http.Request) (string, error) // ExtractBearerToken is a RequestTokenExtractor which extracts a bearer token from a request's // Authorization header. func ExtractBearerToken(r *http.Request) (string, error) { ah := r.Header.Get("Authorization") if ah == "" { return "", errors.New("missing Authorization header") } if len(ah) <= 6 || strings.ToUpper(ah[0:6]) != "BEARER" { return "", errors.New("should be a bearer token") } val := ah[7:] if len(val) == 0 { return "", errors.New("bearer token is empty") } return val, nil } // CookieTokenExtractor returns a RequestTokenExtractor which extracts a token from the named cookie in a request. func CookieTokenExtractor(cookieName string) RequestTokenExtractor { return func(r *http.Request) (string, error) { ck, err := r.Cookie(cookieName) if err != nil { return "", fmt.Errorf("token cookie not found in request: %v", err) } if ck.Value == "" { return "", errors.New("token cookie found but is empty") } return ck.Value, nil } } func NewClaims(iss, sub string, aud interface{}, iat, exp time.Time) jose.Claims { return jose.Claims{ // required "iss": iss, "sub": sub, "aud": aud, "iat": iat.Unix(), "exp": exp.Unix(), } } func GenClientID(hostport string) (string, error) { b, err := randBytes(32) if err != nil { return "", err } var host string if strings.Contains(hostport, ":") { host, _, err = net.SplitHostPort(hostport) if err != nil { return "", err } } else { host = hostport } return fmt.Sprintf("%s@%s", base64.URLEncoding.EncodeToString(b), host), nil } func randBytes(n int) ([]byte, error) { b := make([]byte, n) got, err := rand.Read(b) if err != nil { return nil, err } else if n != got { return nil, errors.New("unable to generate enough random data") } return b, nil } // urlEqual checks two urls for equality using only the host and path portions. func urlEqual(url1, url2 string) bool { u1, err := url.Parse(url1) if err != nil { return false } u2, err := url.Parse(url2) if err != nil { return false } return strings.ToLower(u1.Host+u1.Path) == strings.ToLower(u2.Host+u2.Path) }