blob: 3f77bc87751de44b2beeee8a8be17be270f0dd61 [file] [log] [blame]
giolekva603e73a2021-10-22 14:46:45 +04001package main
2
3import (
4 "bytes"
giolekvadd750802021-11-07 13:24:21 +04005 "crypto/tls"
giolekva603e73a2021-10-22 14:46:45 +04006 "embed"
7 "encoding/json"
8 "errors"
9 "flag"
10 "fmt"
11 "html/template"
12 "io"
13 "io/ioutil"
14 "log"
15 "net/http"
16 "net/http/cookiejar"
17 "net/url"
18
19 "github.com/gorilla/mux"
20 "github.com/itaysk/regogo"
21)
22
23var port = flag.Int("port", 8080, "Port to listen on")
24var kratos = flag.String("kratos", "https://accounts.lekva.me", "Kratos URL")
giolekva788dc6e2021-10-25 20:40:53 +040025var hydra = flag.String("hydra", "hydra.pcloud", "Hydra admin server address")
giolekvadd750802021-11-07 13:24:21 +040026var emailDomain = flag.String("email-domain", "lekva.me", "Email domain")
giolekva603e73a2021-10-22 14:46:45 +040027
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +040028var apiPort = flag.Int("api-port", 8081, "API Port to listen on")
29var kratosAPI = flag.String("kratos-api", "", "Kratos API address")
30
Giorgi Lekveishvilid76414e2023-12-21 13:30:23 +040031var enableRegistration = flag.Bool("enable-registration", false, "If true account registration will be enabled")
32
giolekva603e73a2021-10-22 14:46:45 +040033var ErrNotLoggedIn = errors.New("Not logged in")
34
35//go:embed templates/*
36var tmpls embed.FS
37
giolekva47031752021-11-12 14:34:33 +040038//go:embed static
39var static embed.FS
40
giolekva603e73a2021-10-22 14:46:45 +040041type Templates struct {
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +040042 WhoAmI *template.Template
43 Register *template.Template
44 Login *template.Template
45 Consent *template.Template
giolekva603e73a2021-10-22 14:46:45 +040046}
47
48func ParseTemplates(fs embed.FS) (*Templates, error) {
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +040049 base, err := template.ParseFS(fs, "templates/base.html")
giolekva788dc6e2021-10-25 20:40:53 +040050 if err != nil {
51 return nil, err
52 }
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +040053 parse := func(path string) (*template.Template, error) {
54 if b, err := base.Clone(); err != nil {
55 return nil, err
56 } else {
57 return b.ParseFS(fs, path)
58 }
59 }
60 whoami, err := parse("templates/whoami.html")
giolekva603e73a2021-10-22 14:46:45 +040061 if err != nil {
62 return nil, err
63 }
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +040064 register, err := parse("templates/register.html")
giolekva603e73a2021-10-22 14:46:45 +040065 if err != nil {
66 return nil, err
67 }
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +040068 login, err := parse("templates/login.html")
giolekva603e73a2021-10-22 14:46:45 +040069 if err != nil {
70 return nil, err
71 }
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +040072 consent, err := parse("templates/consent.html")
73 if err != nil {
74 return nil, err
75 }
76 return &Templates{whoami, register, login, consent}, nil
giolekva603e73a2021-10-22 14:46:45 +040077}
78
79type Server struct {
Giorgi Lekveishvilid76414e2023-12-21 13:30:23 +040080 r *mux.Router
81 serv *http.Server
82 kratos string
83 hydra *HydraClient
84 tmpls *Templates
85 enableRegistration bool
giolekva603e73a2021-10-22 14:46:45 +040086}
87
Giorgi Lekveishvilid76414e2023-12-21 13:30:23 +040088func NewServer(port int, kratos string, hydra *HydraClient, tmpls *Templates, enableRegistration bool) *Server {
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +040089 r := mux.NewRouter()
90 serv := &http.Server{
91 Addr: fmt.Sprintf(":%d", port),
92 Handler: r,
93 }
Giorgi Lekveishvilid76414e2023-12-21 13:30:23 +040094 return &Server{r, serv, kratos, hydra, tmpls, enableRegistration}
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +040095}
96
giolekva47031752021-11-12 14:34:33 +040097func cacheControlWrapper(h http.Handler) http.Handler {
98 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
99 // TODO(giolekva): enable caching
100 // w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
101 h.ServeHTTP(w, r)
102 })
103}
104
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +0400105func (s *Server) Start() error {
giolekva47031752021-11-12 14:34:33 +0400106 var staticFS = http.FS(static)
107 fs := http.FileServer(staticFS)
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +0400108 s.r.PathPrefix("/static/").Handler(cacheControlWrapper(fs))
Giorgi Lekveishvilid76414e2023-12-21 13:30:23 +0400109 if s.enableRegistration {
110 s.r.Path("/register").Methods(http.MethodGet).HandlerFunc(s.registerInitiate)
111 s.r.Path("/register").Methods(http.MethodPost).HandlerFunc(s.register)
112 }
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +0400113 s.r.Path("/login").Methods(http.MethodGet).HandlerFunc(s.loginInitiate)
114 s.r.Path("/login").Methods(http.MethodPost).HandlerFunc(s.login)
115 s.r.Path("/consent").Methods(http.MethodGet).HandlerFunc(s.consent)
116 s.r.Path("/consent").Methods(http.MethodPost).HandlerFunc(s.processConsent)
117 s.r.Path("/logout").Methods(http.MethodGet).HandlerFunc(s.logout)
118 s.r.Path("/").HandlerFunc(s.whoami)
119 return s.serv.ListenAndServe()
giolekva603e73a2021-10-22 14:46:45 +0400120}
121
122func getCSRFToken(flowType, flow string, cookies []*http.Cookie) (string, error) {
123 jar, err := cookiejar.New(nil)
124 if err != nil {
125 return "", err
126 }
127 client := &http.Client{
128 Jar: jar,
giolekvadd750802021-11-07 13:24:21 +0400129 Transport: &http.Transport{
130 TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
131 },
giolekva603e73a2021-10-22 14:46:45 +0400132 }
giolekvadd750802021-11-07 13:24:21 +0400133 b, err := url.Parse(*kratos + "/self-service/" + flowType + "/browser")
giolekva603e73a2021-10-22 14:46:45 +0400134 if err != nil {
135 return "", err
136 }
137 client.Jar.SetCookies(b, cookies)
giolekvadd750802021-11-07 13:24:21 +0400138 resp, err := client.Get(fmt.Sprintf(*kratos+"/self-service/"+flowType+"/flows?id=%s", flow))
giolekva603e73a2021-10-22 14:46:45 +0400139 if err != nil {
140 return "", err
141 }
142 respBody, err := ioutil.ReadAll(resp.Body)
143 if err != nil {
144 return "", err
145 }
146 token, err := regogo.Get(string(respBody), "input.ui.nodes[0].attributes.value")
147 if err != nil {
148 return "", err
149 }
150 return token.String(), nil
151}
152
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +0400153func (s *Server) registerInitiate(w http.ResponseWriter, r *http.Request) {
giolekva603e73a2021-10-22 14:46:45 +0400154 if err := r.ParseForm(); err != nil {
155 http.Error(w, err.Error(), http.StatusInternalServerError)
156 return
157 }
158 flow, ok := r.Form["flow"]
159 if !ok {
160 http.Redirect(w, r, s.kratos+"/self-service/registration/browser", http.StatusSeeOther)
161 return
162 }
163 csrfToken, err := getCSRFToken("registration", flow[0], r.Cookies())
164 if err != nil {
165 http.Error(w, err.Error(), http.StatusInternalServerError)
166 return
167 }
giolekva603e73a2021-10-22 14:46:45 +0400168 w.Header().Set("Content-Type", "text/html")
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +0400169 if err := s.tmpls.Register.Execute(w, csrfToken); err != nil {
giolekva603e73a2021-10-22 14:46:45 +0400170 http.Error(w, err.Error(), http.StatusInternalServerError)
171 return
172 }
173}
174
175type regReq struct {
176 CSRFToken string `json:"csrf_token"`
177 Method string `json:"method"`
178 Password string `json:"password"`
179 Traits regReqTraits `json:"traits"`
180}
181
182type regReqTraits struct {
183 Username string `json:"username"`
184}
185
Giorgi Lekveishvili58cb1482023-12-04 12:33:49 +0400186func (s *Server) register(w http.ResponseWriter, r *http.Request) {
giolekva603e73a2021-10-22 14:46:45 +0400187 if err := r.ParseForm(); err != nil {
188 http.Error(w, err.Error(), http.StatusInternalServerError)
189 return
190 }
191 flow, ok := r.Form["flow"]
192 if !ok {
193 http.Redirect(w, r, s.kratos+"/self-service/registration/browser", http.StatusSeeOther)
194 return
195 }
196 req := regReq{
197 CSRFToken: r.FormValue("csrf_token"),
198 Method: "password",
199 Password: r.FormValue("password"),
200 Traits: regReqTraits{
201 Username: r.FormValue("username"),
202 },
203 }
204 var reqBody bytes.Buffer
205 if err := json.NewEncoder(&reqBody).Encode(req); err != nil {
206 http.Error(w, err.Error(), http.StatusInternalServerError)
207 return
208 }
209 if resp, err := postToKratos("registration", flow[0], r.Cookies(), &reqBody); err != nil {
210 http.Error(w, err.Error(), http.StatusInternalServerError)
211 return
212 } else {
213 for _, c := range resp.Cookies() {
214 http.SetCookie(w, c)
215 }
216 http.Redirect(w, r, "/", http.StatusSeeOther)
217 }
218}
219
220// Login flow
221
222func (s *Server) loginInitiate(w http.ResponseWriter, r *http.Request) {
223 if err := r.ParseForm(); err != nil {
224 http.Error(w, err.Error(), http.StatusInternalServerError)
225 return
226 }
giolekva788dc6e2021-10-25 20:40:53 +0400227 if challenge, ok := r.Form["login_challenge"]; ok {
Giorgi Lekveishvili7016d882024-04-09 09:06:53 +0400228 username, err := getWhoAmIFromKratos(r.Cookies())
229 if err != nil && err != ErrNotLoggedIn {
230 http.Error(w, err.Error(), http.StatusInternalServerError)
231 return
232 }
233 if err == nil {
234 redirectTo, err := s.hydra.LoginAcceptChallenge(challenge[0], username)
235 if err != nil {
236 http.Error(w, err.Error(), http.StatusInternalServerError)
237 return
238 }
239 http.Redirect(w, r, redirectTo, http.StatusSeeOther)
240 return
241 }
giolekva788dc6e2021-10-25 20:40:53 +0400242 // TODO(giolekva): encrypt
243 http.SetCookie(w, &http.Cookie{
244 Name: "login_challenge",
245 Value: challenge[0],
246 HttpOnly: true,
247 })
giolekva788dc6e2021-10-25 20:40:53 +0400248 }
Giorgi Lekveishvili0ba5e402024-03-20 15:56:30 +0400249 returnTo := r.Form.Get("return_to")
giolekva603e73a2021-10-22 14:46:45 +0400250 flow, ok := r.Form["flow"]
251 if !ok {
Giorgi Lekveishvili0ba5e402024-03-20 15:56:30 +0400252 addr := s.kratos + "/self-service/login/browser"
253 if returnTo != "" {
254 addr += fmt.Sprintf("?return_to=%s", returnTo)
255 }
256 http.Redirect(w, r, addr, http.StatusSeeOther)
giolekva603e73a2021-10-22 14:46:45 +0400257 return
258 }
259 csrfToken, err := getCSRFToken("login", flow[0], r.Cookies())
260 if err != nil {
261 http.Error(w, err.Error(), http.StatusInternalServerError)
262 return
263 }
giolekva603e73a2021-10-22 14:46:45 +0400264 w.Header().Set("Content-Type", "text/html")
Giorgi Lekveishvilid76414e2023-12-21 13:30:23 +0400265 if err := s.tmpls.Login.Execute(w, map[string]any{
266 "csrfToken": csrfToken,
267 "enableRegistration": s.enableRegistration,
268 }); err != nil {
giolekva603e73a2021-10-22 14:46:45 +0400269 http.Error(w, err.Error(), http.StatusInternalServerError)
270 return
271 }
272}
273
274type loginReq struct {
275 CSRFToken string `json:"csrf_token"`
276 Method string `json:"method"`
277 Password string `json:"password"`
278 Username string `json:"password_identifier"`
279}
280
281func postToKratos(flowType, flow string, cookies []*http.Cookie, req io.Reader) (*http.Response, error) {
282 jar, err := cookiejar.New(nil)
283 if err != nil {
284 return nil, err
285 }
286 client := &http.Client{
287 Jar: jar,
giolekvadd750802021-11-07 13:24:21 +0400288 Transport: &http.Transport{
289 TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
290 },
giolekva603e73a2021-10-22 14:46:45 +0400291 }
giolekvadd750802021-11-07 13:24:21 +0400292 b, err := url.Parse(*kratos + "/self-service/" + flowType + "/browser")
giolekva603e73a2021-10-22 14:46:45 +0400293 if err != nil {
294 return nil, err
295 }
296 client.Jar.SetCookies(b, cookies)
giolekvadd750802021-11-07 13:24:21 +0400297 resp, err := client.Post(fmt.Sprintf(*kratos+"/self-service/"+flowType+"?flow=%s", flow), "application/json", req)
giolekva603e73a2021-10-22 14:46:45 +0400298 if err != nil {
299 return nil, err
300 }
301 return resp, nil
302}
303
Giorgi Lekveishvili0ba5e402024-03-20 15:56:30 +0400304func postFormToKratos(flowType, flow string, cookies []*http.Cookie, data url.Values) (*http.Response, error) {
305 jar, err := cookiejar.New(nil)
306 if err != nil {
307 return nil, err
308 }
309 client := &http.Client{
310 Jar: jar,
311 Transport: &http.Transport{
312 TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
313 },
314 CheckRedirect: func(req *http.Request, via []*http.Request) error {
315 return http.ErrUseLastResponse
316 },
317 }
318 b, err := url.Parse(*kratos + "/self-service/" + flowType + "/browser")
319 if err != nil {
320 return nil, err
321 }
322 client.Jar.SetCookies(b, cookies)
323 resp, err := client.PostForm(fmt.Sprintf(*kratos+"/self-service/"+flowType+"?flow=%s", flow), data)
324 if err != nil {
325 return nil, err
326 }
327 return resp, nil
328}
329
giolekva603e73a2021-10-22 14:46:45 +0400330type logoutResp struct {
331 LogoutURL string `json:"logout_url"`
332}
333
334func getLogoutURLFromKratos(cookies []*http.Cookie) (string, error) {
335 jar, err := cookiejar.New(nil)
336 if err != nil {
337 return "", err
338 }
339 client := &http.Client{
340 Jar: jar,
giolekvadd750802021-11-07 13:24:21 +0400341 Transport: &http.Transport{
342 TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
343 },
giolekva603e73a2021-10-22 14:46:45 +0400344 }
giolekvadd750802021-11-07 13:24:21 +0400345 b, err := url.Parse(*kratos + "/self-service/logout/browser")
giolekva603e73a2021-10-22 14:46:45 +0400346 if err != nil {
347 return "", err
348 }
349 client.Jar.SetCookies(b, cookies)
giolekvadd750802021-11-07 13:24:21 +0400350 resp, err := client.Get(*kratos + "/self-service/logout/browser")
giolekva603e73a2021-10-22 14:46:45 +0400351 if err != nil {
352 return "", err
353 }
354 var lr logoutResp
355 if err := json.NewDecoder(resp.Body).Decode(&lr); err != nil {
356 return "", err
357 }
358 return lr.LogoutURL, nil
359}
360
361func getWhoAmIFromKratos(cookies []*http.Cookie) (string, error) {
362 jar, err := cookiejar.New(nil)
363 if err != nil {
364 return "", err
365 }
366 client := &http.Client{
367 Jar: jar,
giolekvadd750802021-11-07 13:24:21 +0400368 Transport: &http.Transport{
369 TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
370 },
giolekva603e73a2021-10-22 14:46:45 +0400371 }
giolekvadd750802021-11-07 13:24:21 +0400372 b, err := url.Parse(*kratos + "/sessions/whoami")
giolekva603e73a2021-10-22 14:46:45 +0400373 if err != nil {
374 return "", err
375 }
376 client.Jar.SetCookies(b, cookies)
giolekvadd750802021-11-07 13:24:21 +0400377 resp, err := client.Get(*kratos + "/sessions/whoami")
giolekva603e73a2021-10-22 14:46:45 +0400378 if err != nil {
379 return "", err
380 }
381 respBody, err := ioutil.ReadAll(resp.Body)
382 if err != nil {
383 return "", err
384 }
385 username, err := regogo.Get(string(respBody), "input.identity.traits.username")
386 if err != nil {
387 return "", err
388 }
389 if username.String() == "" {
390 return "", ErrNotLoggedIn
391 }
392 return username.String(), nil
393
394}
395
giolekva788dc6e2021-10-25 20:40:53 +0400396func extractError(r io.Reader) error {
397 respBody, err := ioutil.ReadAll(r)
398 if err != nil {
399 return err
400 }
Giorgi Lekveishvili0ba5e402024-03-20 15:56:30 +0400401 fmt.Printf("++ %s\n", respBody)
giolekva788dc6e2021-10-25 20:40:53 +0400402 t, err := regogo.Get(string(respBody), "input.ui.messages[0].type")
403 if err != nil {
404 return err
405 }
406 if t.String() == "error" {
407 message, err := regogo.Get(string(respBody), "input.ui.messages[0].text")
408 if err != nil {
409 return err
410 }
411 return errors.New(message.String())
412 }
413 return nil
414}
415
giolekva603e73a2021-10-22 14:46:45 +0400416func (s *Server) login(w http.ResponseWriter, r *http.Request) {
417 if err := r.ParseForm(); err != nil {
418 http.Error(w, err.Error(), http.StatusInternalServerError)
419 return
420 }
421 flow, ok := r.Form["flow"]
422 if !ok {
423 http.Redirect(w, r, s.kratos+"/self-service/login/browser", http.StatusSeeOther)
424 return
425 }
Giorgi Lekveishvili0ba5e402024-03-20 15:56:30 +0400426 req := url.Values{
427 "csrf_token": []string{r.FormValue("csrf_token")},
428 "method": []string{"password"},
429 "password": []string{r.FormValue("password")},
430 "identifier": []string{r.FormValue("username")},
giolekva603e73a2021-10-22 14:46:45 +0400431 }
Giorgi Lekveishvili0ba5e402024-03-20 15:56:30 +0400432 resp, err := postFormToKratos("login", flow[0], r.Cookies(), req)
433 fmt.Printf("--- %d\n", resp.StatusCode)
434 var vv bytes.Buffer
435 io.Copy(&vv, resp.Body)
436 fmt.Println(vv.String())
giolekva788dc6e2021-10-25 20:40:53 +0400437 if err != nil {
giolekvaeb590282021-10-22 17:31:40 +0400438 if challenge, _ := r.Cookie("login_challenge"); challenge != nil {
giolekva788dc6e2021-10-25 20:40:53 +0400439 redirectTo, err := s.hydra.LoginRejectChallenge(challenge.Value, err.Error())
giolekvaeb590282021-10-22 17:31:40 +0400440 if err != nil {
441 http.Error(w, err.Error(), http.StatusInternalServerError)
442 return
443 }
giolekva788dc6e2021-10-25 20:40:53 +0400444 http.Redirect(w, r, redirectTo, http.StatusSeeOther)
445 return
giolekvaeb590282021-10-22 17:31:40 +0400446 }
giolekva788dc6e2021-10-25 20:40:53 +0400447 http.Error(w, err.Error(), http.StatusInternalServerError)
448 return
giolekva603e73a2021-10-22 14:46:45 +0400449 }
giolekva788dc6e2021-10-25 20:40:53 +0400450 for _, c := range resp.Cookies() {
451 http.SetCookie(w, c)
452 }
453 if challenge, _ := r.Cookie("login_challenge"); challenge != nil {
454 username, err := getWhoAmIFromKratos(resp.Cookies())
455 if err != nil {
456 http.Error(w, err.Error(), http.StatusInternalServerError)
457 return
458 }
459 redirectTo, err := s.hydra.LoginAcceptChallenge(challenge.Value, username)
460 if err != nil {
461 http.Error(w, err.Error(), http.StatusInternalServerError)
462 return
463 }
464 http.Redirect(w, r, redirectTo, http.StatusSeeOther)
465 return
466 }
Giorgi Lekveishvili0ba5e402024-03-20 15:56:30 +0400467 if resp.StatusCode == http.StatusSeeOther {
468 http.Redirect(w, r, resp.Header.Get("Location"), http.StatusSeeOther)
469 } else {
470 http.Redirect(w, r, "/", http.StatusSeeOther)
471 }
giolekva603e73a2021-10-22 14:46:45 +0400472}
473
474func (s *Server) logout(w http.ResponseWriter, r *http.Request) {
475 if logoutURL, err := getLogoutURLFromKratos(r.Cookies()); err != nil {
476 http.Error(w, err.Error(), http.StatusInternalServerError)
477 return
478 } else {
479 http.Redirect(w, r, logoutURL, http.StatusSeeOther)
480 }
481}
482
483func (s *Server) whoami(w http.ResponseWriter, r *http.Request) {
484 if username, err := getWhoAmIFromKratos(r.Cookies()); err != nil {
485 if errors.Is(err, ErrNotLoggedIn) {
486 http.Redirect(w, r, "/login", http.StatusSeeOther)
487 return
488 }
489 http.Error(w, err.Error(), http.StatusInternalServerError)
490 } else {
491 if err := s.tmpls.WhoAmI.Execute(w, username); err != nil {
492 http.Error(w, err.Error(), http.StatusInternalServerError)
493 }
494 }
495}
496
giolekva788dc6e2021-10-25 20:40:53 +0400497// TODO(giolekva): verify if logged in
498func (s *Server) consent(w http.ResponseWriter, r *http.Request) {
499 if err := r.ParseForm(); err != nil {
500 http.Error(w, err.Error(), http.StatusBadRequest)
501 return
502 }
503 challenge, ok := r.Form["consent_challenge"]
504 if !ok {
505 http.Error(w, "Consent challenge not provided", http.StatusBadRequest)
506 return
507 }
508 consent, err := s.hydra.GetConsentChallenge(challenge[0])
509 if err != nil {
510 http.Error(w, err.Error(), http.StatusInternalServerError)
511 return
512 }
Giorgi Lekveishvili1f2c1c52024-04-12 07:17:58 +0400513 username, err := getWhoAmIFromKratos(r.Cookies())
514 if err != nil {
giolekva788dc6e2021-10-25 20:40:53 +0400515 http.Error(w, err.Error(), http.StatusInternalServerError)
516 return
517 }
Giorgi Lekveishvili1f2c1c52024-04-12 07:17:58 +0400518 acceptedScopes := consent.RequestedScopes
519 idToken := map[string]string{
520 "username": username,
521 "email": username + "@" + *emailDomain,
522 }
523 // TODO(gio): is auto consent safe? should such behaviour be configurable?
524 if redirectTo, err := s.hydra.ConsentAccept(r.FormValue("consent_challenge"), acceptedScopes, idToken); err != nil {
525 http.Error(w, err.Error(), http.StatusInternalServerError)
526 } else {
527 http.Redirect(w, r, redirectTo, http.StatusSeeOther)
528 }
529 // w.Header().Set("Content-Type", "text/html")
530 // if err := s.tmpls.Consent.Execute(w, consent.RequestedScopes); err != nil {
531 // http.Error(w, err.Error(), http.StatusInternalServerError)
532 // return
533 // }
giolekva788dc6e2021-10-25 20:40:53 +0400534}
535
536func (s *Server) processConsent(w http.ResponseWriter, r *http.Request) {
537 if err := r.ParseForm(); err != nil {
538 http.Error(w, err.Error(), http.StatusBadRequest)
539 return
540 }
541 username, err := getWhoAmIFromKratos(r.Cookies())
542 if err != nil {
543 http.Error(w, err.Error(), http.StatusInternalServerError)
544 return
545 }
546 if _, accepted := r.Form["allow"]; accepted {
547 acceptedScopes, _ := r.Form["scope"]
548 idToken := map[string]string{
549 "username": username,
giolekvadd750802021-11-07 13:24:21 +0400550 "email": username + "@" + *emailDomain,
giolekva788dc6e2021-10-25 20:40:53 +0400551 }
552 if redirectTo, err := s.hydra.ConsentAccept(r.FormValue("consent_challenge"), acceptedScopes, idToken); err != nil {
553 http.Error(w, err.Error(), http.StatusInternalServerError)
554 } else {
555 http.Redirect(w, r, redirectTo, http.StatusSeeOther)
556 }
557 return
558 } else {
559 // TODO(giolekva): implement rejection logic
560 }
561}
562
giolekva603e73a2021-10-22 14:46:45 +0400563func main() {
564 flag.Parse()
565 t, err := ParseTemplates(tmpls)
566 if err != nil {
567 log.Fatal(err)
568 }
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +0400569 go func() {
570 s := NewAPIServer(*apiPort, *kratosAPI)
571 log.Fatal(s.Start())
572 }()
573 func() {
574 s := NewServer(
575 *port,
576 *kratos,
577 NewHydraClient(*hydra),
578 t,
Giorgi Lekveishvilid76414e2023-12-21 13:30:23 +0400579 *enableRegistration,
Giorgi Lekveishvilifedd0062023-12-21 10:52:49 +0400580 )
581 log.Fatal(s.Start())
582 }()
giolekva603e73a2021-10-22 14:46:45 +0400583}