forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
implicit.go
151 lines (126 loc) · 3.74 KB
/
implicit.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
package login
import (
"fmt"
"html/template"
"net/http"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/auth/user"
utilruntime "k8s.io/kubernetes/pkg/util/runtime"
"github.com/openshift/origin/pkg/auth/authenticator"
"github.com/openshift/origin/pkg/auth/oauth/handlers"
"github.com/openshift/origin/pkg/auth/server/csrf"
)
type RequestAuthenticator interface {
authenticator.Request
handlers.AuthenticationSuccessHandler
}
type ConfirmFormRenderer interface {
Render(form ConfirmForm, w http.ResponseWriter, req *http.Request)
}
type ConfirmForm struct {
Action string
Error string
User user.Info
Values ConfirmFormValues
}
type ConfirmFormValues struct {
Then string
CSRF string
}
type Confirm struct {
csrf csrf.CSRF
auth RequestAuthenticator
render ConfirmFormRenderer
}
func NewConfirm(csrf csrf.CSRF, auth RequestAuthenticator, render ConfirmFormRenderer) *Confirm {
return &Confirm{
csrf: csrf,
auth: auth,
render: render,
}
}
func (c *Confirm) ServeHTTP(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case "GET":
c.handleConfirmForm(w, req)
case "POST":
c.handleConfirm(w, req)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func (c *Confirm) handleConfirmForm(w http.ResponseWriter, req *http.Request) {
uri, err := getBaseURL(req)
if err != nil {
glog.Errorf("Unable to generate base URL: %v", err)
http.Error(w, "Unable to determine URL", http.StatusInternalServerError)
return
}
form := ConfirmForm{
Action: uri.String(),
}
if then := req.URL.Query().Get("then"); then != "" {
// TODO: sanitize 'then'
form.Values.Then = then
}
switch req.URL.Query().Get("reason") {
case "":
break
default:
form.Error = "An unknown error has occurred. Please try again."
}
csrf, err := c.csrf.Generate(w, req)
if err != nil {
utilruntime.HandleError(fmt.Errorf("unable to generate CSRF token: %v", err))
}
form.Values.CSRF = csrf
user, ok, err := c.auth.AuthenticateRequest(req)
if err != nil || !ok {
glog.Errorf("Unable to authenticate request: %v", err)
form.Error = "An unknown error has occurred. Contact your administrator."
c.render.Render(form, w, req)
return
}
form.User = user
c.render.Render(form, w, req)
}
func (c *Confirm) handleConfirm(w http.ResponseWriter, req *http.Request) {
if ok, err := c.csrf.Check(req, req.FormValue("csrf")); !ok || err != nil {
glog.Errorf("Unable to check CSRF token: %v", err)
failed("token expired", w, req)
return
}
user, ok, err := c.auth.AuthenticateRequest(req)
if err != nil || !ok {
if err != nil {
glog.Errorf("Unable authenticate request: %v", err)
}
failed("access denied", w, req)
return
}
then := req.FormValue("then")
c.auth.AuthenticationSucceeded(user, then, w, req)
}
var DefaultConfirmFormRenderer = confirmTemplateRenderer{}
type confirmTemplateRenderer struct{}
func (r confirmTemplateRenderer) Render(form ConfirmForm, w http.ResponseWriter, req *http.Request) {
w.Header().Add("Content-Type", "text/html; charset=UTF-8")
w.WriteHeader(http.StatusOK)
if err := confirmTemplate.Execute(w, form); err != nil {
utilruntime.HandleError(fmt.Errorf("unable render confirm template: %v", err))
}
}
var confirmTemplate = template.Must(template.New("ConfirmForm").Parse(`
{{ if .Error }}<div class="message">{{ .Error }}</div>{{ end }}
<form action="{{ .Action }}" method="POST">
<input type="hidden" name="then" value="{{ .Values.Then }}">
<input type="hidden" name="csrf" value="{{ .Values.CSRF }}">
{{ if .User }}
<p>You are now logged in as <strong>{{ .User.GetName }}</strong></p>
<input type="submit" name="Continue">
{{ else }}
<p>You are not currently logged in.</p>
<input type="submit" disabled="disabled" name="Continue">
{{ end }}
</form>
`))