forked from rhinoman/couchdb-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.go
113 lines (93 loc) · 2.94 KB
/
auth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package couchdb
import (
"encoding/base64"
"fmt"
"net/http"
)
//Basic interface for Auth
type Auth interface {
//Adds authentication headers to a request
AddAuthHeaders(*http.Request)
//Extracts Updated auth info from Couch Response
updateAuth(*http.Response)
//Sets updated auth (headers, cookies, etc.) in an http response
//For the update function, the map keys are cookie and/or header names
GetUpdatedAuth() map[string]string
//Purely for debug purposes. Do not call, ever.
DebugString() string
}
//HTTP Basic Authentication support
type BasicAuth struct {
Username string
Password string
}
//Pass-through Auth header
type PassThroughAuth struct {
AuthHeader string
}
//Cookie-based auth (for sessions)
type CookieAuth struct {
AuthToken string
UpdatedAuthToken string
}
//Adds Basic Authentication headers to an http request
func (ba *BasicAuth) AddAuthHeaders(req *http.Request) {
authString := []byte(ba.Username + ":" + ba.Password)
header := "Basic " + base64.StdEncoding.EncodeToString(authString)
req.Header.Set("Authorization", string(header))
}
//Use if you already have an Authentication header you want to pass through to couchdb
func (pta *PassThroughAuth) AddAuthHeaders(req *http.Request) {
req.Header.Set("Authorization", pta.AuthHeader)
}
//Adds session token to request
func (ca *CookieAuth) AddAuthHeaders(req *http.Request) {
authString := "AuthSession=" + ca.AuthToken
req.Header.Set("Cookie", authString)
req.Header.Set("X-CouchDB-WWW-Authenticate", "Cookie")
}
//Update Auth Data
//If couchdb generates a new token, place it in a separate field so that
//it is available to an application
//do nothing for basic auth
func (ba *BasicAuth) updateAuth(resp *http.Response) {}
//Couchdb returns updated AuthSession tokens
func (ca *CookieAuth) updateAuth(resp *http.Response) {
for _, cookie := range resp.Cookies() {
if cookie.Name == "AuthSession" {
ca.UpdatedAuthToken = cookie.Value
}
}
}
//do nothing for pass through
func (pta *PassThroughAuth) updateAuth(resp *http.Response) {}
//Get Updated Auth
//Does nothing for BasicAuth
func (ba *BasicAuth) GetUpdatedAuth() map[string]string {
return nil
}
//Does nothing for PassThroughAuth
func (pta *PassThroughAuth) GetUpdatedAuth() map[string]string {
return nil
}
//Set AuthSession Cookie
func (ca *CookieAuth) GetUpdatedAuth() map[string]string {
am := make(map[string]string)
if ca.UpdatedAuthToken != "" {
am["AuthSession"] = ca.UpdatedAuthToken
}
return am
}
//Return a Debug string
func (ba *BasicAuth) DebugString() string {
return fmt.Sprintf("Username: %v, Password: %v", ba.Username, ba.Password)
}
func (pta *PassThroughAuth) DebugString() string {
return fmt.Sprintf("Authorization Header: %v", pta.AuthHeader)
}
func (ca *CookieAuth) DebugString() string {
return fmt.Sprintf("AuthToken: %v, Updated AuthToken: %v",
ca.AuthToken, ca.UpdatedAuthToken)
}
//TODO: Add support for other Authentication methods supported by Couch:
//OAuth, Proxy, etc.