-
Notifications
You must be signed in to change notification settings - Fork 3
/
cookie.go
151 lines (135 loc) · 4.54 KB
/
cookie.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// based on https://github.com/42wim/crewjam-saml
package samlplugin
import (
// "fmt"
"net/http"
"strings"
"time"
"github.com/42wim/crewjam-saml"
// "github.com/davecgh/go-spew/spew"
)
// ClientState implements client side storage for state.
type ClientState interface {
SetState(w http.ResponseWriter, r *http.Request, id string, value string)
GetStates(r *http.Request) map[string]string
GetState(r *http.Request, id string) string
DeleteState(w http.ResponseWriter, r *http.Request, id string) error
SetSession(w http.ResponseWriter, r *http.Request, id string, value string)
GetSessions(r *http.Request) map[string]string
DeleteSession(w http.ResponseWriter, r *http.Request, id string) error
}
// ClientToken implements client side storage for signed authorization tokens.
type ClientToken interface {
GetToken(r *http.Request) string
SetToken(w http.ResponseWriter, r *http.Request, value string, maxAge time.Duration)
}
const stateCookiePrefix = "saml_"
const sessionCookiePrefix = "cddsml_session_"
const defaultCookieName = "token"
// ClientCookies implements ClientState and ClientToken using cookies.
type ClientCookies struct {
ServiceProvider *saml.ServiceProvider
Name string
Domain string
Secure bool
}
func (c ClientCookies) SetSession(w http.ResponseWriter, r *http.Request, id string, value string) {
//fmt.Println("setting session", sessionCookiePrefix+id, value)
http.SetCookie(w, &http.Cookie{
Name: sessionCookiePrefix + id,
Value: value,
MaxAge: 86400,
HttpOnly: true,
Secure: c.Secure || r.URL.Scheme == "https",
Path: "/",
})
}
// GetSessions returns the currently stored states by reading cookies.
func (c ClientCookies) GetSessions(r *http.Request) map[string]string {
rv := map[string]string{}
for _, cookie := range r.Cookies() {
if !strings.HasPrefix(cookie.Name, sessionCookiePrefix) {
continue
}
name := strings.TrimPrefix(cookie.Name, sessionCookiePrefix)
rv[name] = cookie.Value
}
return rv
}
// DeleteSession removes the named stored state by clearing the corresponding cookie.
func (c ClientCookies) DeleteSession(w http.ResponseWriter, r *http.Request, id string) error {
cookie, err := r.Cookie(sessionCookiePrefix + id)
if err != nil {
return err
}
cookie.Value = ""
cookie.Path = "/"
cookie.Expires = time.Unix(1, 0) // past time as close to epoch as possible, but not zero time.Time{}
http.SetCookie(w, cookie)
return nil
}
// SetState stores the named state value by setting a cookie.
func (c ClientCookies) SetState(w http.ResponseWriter, r *http.Request, id string, value string) {
//fmt.Println("setstate", id, value)
http.SetCookie(w, &http.Cookie{
Name: stateCookiePrefix + id,
Value: value,
MaxAge: int(saml.MaxIssueDelay.Seconds()),
HttpOnly: true,
Secure: c.Secure || r.URL.Scheme == "https",
Path: c.ServiceProvider.AcsURL.Path,
})
}
// GetStates returns the currently stored states by reading cookies.
func (c ClientCookies) GetStates(r *http.Request) map[string]string {
rv := map[string]string{}
for _, cookie := range r.Cookies() {
if !strings.HasPrefix(cookie.Name, stateCookiePrefix) {
continue
}
name := strings.TrimPrefix(cookie.Name, stateCookiePrefix)
rv[name] = cookie.Value
}
return rv
}
// GetState returns a single stored state by reading the cookies
func (c ClientCookies) GetState(r *http.Request, id string) string {
stateCookie, err := r.Cookie(stateCookiePrefix + id)
if err != nil {
return ""
}
return stateCookie.Value
}
// DeleteState removes the named stored state by clearing the corresponding cookie.
func (c ClientCookies) DeleteState(w http.ResponseWriter, r *http.Request, id string) error {
cookie, err := r.Cookie(stateCookiePrefix + id)
if err != nil {
return err
}
cookie.Value = ""
cookie.Expires = time.Unix(1, 0) // past time as close to epoch as possible, but not zero time.Time{}
http.SetCookie(w, cookie)
return nil
}
// SetToken assigns the specified token by setting a cookie.
func (c ClientCookies) SetToken(w http.ResponseWriter, r *http.Request, value string, maxAge time.Duration) {
http.SetCookie(w, &http.Cookie{
Name: c.Name,
Domain: c.Domain,
Value: value,
MaxAge: int(maxAge.Seconds()),
HttpOnly: true,
Secure: c.Secure || r.URL.Scheme == "https",
Path: "/",
})
}
// GetToken returns the token by reading the cookie.
func (c ClientCookies) GetToken(r *http.Request) string {
cookie, err := r.Cookie(c.Name)
if err != nil {
return ""
}
return cookie.Value
}
var _ ClientState = ClientCookies{}
var _ ClientToken = ClientCookies{}