auth

Paddy 2014-09-01 Parent:1aa3a85ff853

25:9fc5fd8196b4 Go to Latest

auth/util.go.old

Rough out client. Remove our old client implementation, and start exploring a new ClientStore interface for storing and retrieving Client data. Keep track of a website for clients.

History
paddy@23 1 package auth
paddy@23 2
paddy@23 3 import (
paddy@23 4 "encoding/base64"
paddy@23 5 "errors"
paddy@23 6 "fmt"
paddy@23 7 "net/http"
paddy@23 8 "net/url"
paddy@23 9 "strings"
paddy@23 10
paddy@23 11 "code.google.com/p/go-uuid/uuid"
paddy@23 12 )
paddy@23 13
paddy@23 14 var (
paddy@23 15 BasicAuthNotSetError = errors.New("Authorization header not set.")
paddy@23 16 InvalidBasicAuthTypeError = errors.New("Invalid basic auth type.")
paddy@23 17 InvalidBasicAuthMessage = errors.New("Invalid basic auth format.")
paddy@23 18 )
paddy@23 19
paddy@23 20 // Parse basic authentication header
paddy@23 21 type BasicAuth struct {
paddy@23 22 Username string
paddy@23 23 Password string
paddy@23 24 }
paddy@23 25
paddy@23 26 // Return authorization header data
paddy@23 27 func CheckBasicAuth(r *http.Request) (BasicAuth, error) {
paddy@23 28 if r.Header.Get("Authorization") == "" {
paddy@23 29 return BasicAuth{}, BasicAuthNotSetError
paddy@23 30 }
paddy@23 31
paddy@23 32 s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
paddy@23 33 if len(s) != 2 || s[0] != "Basic" {
paddy@23 34 return BasicAuth{}, InvalidBasicAuthTypeError
paddy@23 35 }
paddy@23 36
paddy@23 37 b, err := base64.StdEncoding.DecodeString(s[1])
paddy@23 38 if err != nil {
paddy@23 39 return BasicAuth{}, err
paddy@23 40 }
paddy@23 41 pair := strings.SplitN(string(b), ":", 2)
paddy@23 42 if len(pair) != 2 {
paddy@23 43 return BasicAuth{}, InvalidBasicAuthMessage
paddy@23 44 }
paddy@23 45
paddy@23 46 return BasicAuth{Username: pair[0], Password: pair[1]}, nil
paddy@23 47 }
paddy@23 48
paddy@23 49 // getClientAuth checks client basic authentication in params if allowed,
paddy@23 50 // otherwise gets it from the header.
paddy@23 51 func getClientAuth(r *http.Request, allowQueryParams bool) (BasicAuth, error) {
paddy@23 52
paddy@23 53 if allowQueryParams {
paddy@23 54 // Allow for auth without password
paddy@23 55 if _, hasSecret := r.Form["client_secret"]; hasSecret {
paddy@23 56 auth := BasicAuth{
paddy@23 57 Username: r.Form.Get("client_id"),
paddy@23 58 Password: r.Form.Get("client_secret"),
paddy@23 59 }
paddy@23 60 if auth.Username != "" {
paddy@23 61 return auth, nil
paddy@23 62 }
paddy@23 63 }
paddy@23 64 }
paddy@23 65
paddy@23 66 return CheckBasicAuth(r)
paddy@23 67 }
paddy@23 68
paddy@23 69 func newToken() string {
paddy@23 70 return base64.StdEncoding.EncodeToString([]byte(uuid.New()))
paddy@23 71 }
paddy@23 72
paddy@23 73 // validateURI validates that redirectURI is contained in baseURI
paddy@23 74 func validateURI(baseURI string, redirectURI string) error {
paddy@23 75 if baseURI == "" || redirectURI == "" {
paddy@23 76 return errors.New("urls cannot be blank.")
paddy@23 77 }
paddy@23 78
paddy@23 79 // parse base url
paddy@23 80 base, err := url.Parse(baseURI)
paddy@23 81 if err != nil {
paddy@23 82 return err
paddy@23 83 }
paddy@23 84
paddy@23 85 // parse passed url
paddy@23 86 redirect, err := url.Parse(redirectURI)
paddy@23 87 if err != nil {
paddy@23 88 return err
paddy@23 89 }
paddy@23 90
paddy@23 91 // must not have fragment
paddy@23 92 if base.Fragment != "" || redirect.Fragment != "" {
paddy@23 93 return errors.New("url must not include fragment.")
paddy@23 94 }
paddy@23 95
paddy@23 96 // check if urls match
paddy@23 97 if base.Scheme == redirect.Scheme && base.Host == redirect.Host && len(redirect.Path) >= len(base.Path) && strings.HasPrefix(redirect.Path, base.Path) {
paddy@23 98 return nil
paddy@23 99 }
paddy@23 100
paddy@23 101 return errors.New(fmt.Sprintf("urls don't validate: %s / %s\n", baseURI, redirectURI))
paddy@23 102 }