Refactor app, implement logout

This commit is contained in:
Jan Dittberner 2020-12-31 13:19:21 +01:00
parent ce1fac0e68
commit 27e225795c
14 changed files with 647 additions and 349 deletions

View file

@ -12,11 +12,12 @@ import (
type consentHandler struct {
adminClient *admin.Client
logger *log.Logger
}
func (c *consentHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
consentChallenge := request.URL.Query().Get("consent_challenge")
consentRequest, err := c.adminClient.AcceptConsentRequest(
func (h *consentHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
consentChallenge := r.URL.Query().Get("consent_challenge")
consentRequest, err := h.adminClient.AcceptConsentRequest(
admin.NewAcceptConsentRequestParams().WithConsentChallenge(consentChallenge).WithBody(
&models.AcceptConsentRequest{
GrantAccessTokenAudience: nil,
@ -26,14 +27,15 @@ func (c *consentHandler) ServeHTTP(writer http.ResponseWriter, request *http.Req
RememberFor: 86400,
}).WithTimeout(time.Second * 10))
if err != nil {
log.Panic(err)
h.logger.Panic(err)
}
writer.Header().Add("Location", *consentRequest.GetPayload().RedirectTo)
writer.WriteHeader(http.StatusFound)
w.Header().Add("Location", *consentRequest.GetPayload().RedirectTo)
w.WriteHeader(http.StatusFound)
}
func NewConsentHandler(ctx context.Context) *consentHandler {
func NewConsentHandler(logger *log.Logger, ctx context.Context) *consentHandler {
return &consentHandler{
logger: logger,
adminClient: ctx.Value(CtxAdminClient).(*admin.Client),
}
}

20
idp/handlers/error.go Normal file
View file

@ -0,0 +1,20 @@
package handlers
import (
"fmt"
"net/http"
)
type errorHandler struct {
}
func (e *errorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
_, _ = fmt.Fprintf(w, `
didumm %#v
`, r.URL.Query())
}
func NewErrorHandler() *errorHandler {
return &errorHandler{}
}

View file

@ -23,6 +23,7 @@ type loginHandler struct {
bundle *i18n.Bundle
messageCatalog map[string]*i18n.Message
adminClient *admin.Client
logger *log.Logger
}
type LoginInformation struct {
@ -30,27 +31,27 @@ type LoginInformation struct {
Password string `form:"password" validate:"required"`
}
func (h *loginHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
func (h *loginHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var err error
challenge := request.URL.Query().Get("login_challenge")
log.Debugf("received challenge %s\n", challenge)
challenge := r.URL.Query().Get("login_challenge")
h.logger.Debugf("received challenge %s\n", challenge)
validate := validator.New()
switch request.Method {
switch r.Method {
case http.MethodGet:
// GET should render login form
err = h.loginTemplate.Lookup("base").Execute(writer, map[string]interface{}{
err = h.loginTemplate.Lookup("base").Execute(w, map[string]interface{}{
"Title": "Title",
csrf.TemplateTag: csrf.TemplateField(request),
csrf.TemplateTag: csrf.TemplateField(r),
"LabelEmail": "Email",
"LabelPassword": "Password",
"LabelLogin": "Login",
"errors": map[string]string{},
})
if err != nil {
log.Error(err)
http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
h.logger.Error(err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
break
@ -60,23 +61,23 @@ func (h *loginHandler) ServeHTTP(writer http.ResponseWriter, request *http.Reque
// validate input
decoder := form.NewDecoder()
err = decoder.Decode(&loginInfo, request.Form)
err = decoder.Decode(&loginInfo, r.Form)
if err != nil {
log.Error(err)
http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
h.logger.Error(err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
err := validate.Struct(&loginInfo)
if err != nil {
errors := make(map[string]string)
for _, err := range err.(validator.ValidationErrors) {
accept := request.Header.Get("Accept-Language")
accept := r.Header.Get("Accept-Language")
errors[err.Field()] = h.lookupErrorMessage(err.Tag(), err.Field(), err.Value(), i18n.NewLocalizer(h.bundle, accept))
}
err = h.loginTemplate.Lookup("base").Execute(writer, map[string]interface{}{
err = h.loginTemplate.Lookup("base").Execute(w, map[string]interface{}{
"Title": "Title",
csrf.TemplateTag: csrf.TemplateField(request),
csrf.TemplateTag: csrf.TemplateField(r),
"LabelEmail": "Email",
"LabelPassword": "Password",
"LabelLogin": "Login",
@ -84,8 +85,8 @@ func (h *loginHandler) ServeHTTP(writer http.ResponseWriter, request *http.Reque
"errors": errors,
})
if err != nil {
log.Error(err)
http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
h.logger.Error(err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
return
@ -103,13 +104,14 @@ func (h *loginHandler) ServeHTTP(writer http.ResponseWriter, request *http.Reque
Subject: &subject,
}).WithTimeout(time.Second * 10))
if err != nil {
log.Panic(err)
h.logger.Errorf("error getting logout requests: %v", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
writer.Header().Add("Location", *loginRequest.GetPayload().RedirectTo)
writer.WriteHeader(http.StatusFound)
w.Header().Add("Location", *loginRequest.GetPayload().RedirectTo)
w.WriteHeader(http.StatusFound)
break
default:
http.Error(writer, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
}
@ -118,13 +120,13 @@ func (h *loginHandler) lookupErrorMessage(tag string, field string, value interf
var message *i18n.Message
message, ok := h.messageCatalog[fmt.Sprintf("%s-%s", field, tag)]
if !ok {
log.Infof("no specific error message %s-%s", field, tag)
h.logger.Infof("no specific error message %s-%s", field, tag)
message, ok = h.messageCatalog[tag]
if !ok {
log.Infof("no specific error message %s", tag)
h.logger.Infof("no specific error message %s", tag)
message, ok = h.messageCatalog["unknown"]
if !ok {
log.Error("no default translation found")
h.logger.Error("no default translation found")
return tag
}
}
@ -137,18 +139,19 @@ func (h *loginHandler) lookupErrorMessage(tag string, field string, value interf
},
})
if err != nil {
log.Error(err)
h.logger.Error(err)
return tag
}
return translation
}
func NewLoginHandler(ctx context.Context) (*loginHandler, error) {
func NewLoginHandler(logger *log.Logger, ctx context.Context) (*loginHandler, error) {
loginTemplate, err := template.ParseFiles("templates/base.html", "templates/login.html")
if err != nil {
return nil, err
}
return &loginHandler{
logger: logger,
loginTemplate: loginTemplate,
bundle: ctx.Value(services.CtxI18nBundle).(*i18n.Bundle),
messageCatalog: ctx.Value(services.CtxI18nCatalog).(map[string]*i18n.Message),

58
idp/handlers/logout.go Normal file
View file

@ -0,0 +1,58 @@
package handlers
import (
"context"
"net/http"
"time"
"github.com/ory/hydra-client-go/client/admin"
log "github.com/sirupsen/logrus"
)
type logoutHandler struct {
adminClient *admin.Client
logger *log.Logger
}
func (h *logoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
challenge := r.URL.Query().Get("logout_challenge")
h.logger.Debugf("received challenge %s\n", challenge)
logoutRequest, err := h.adminClient.GetLogoutRequest(
admin.NewGetLogoutRequestParams().WithLogoutChallenge(challenge).WithTimeout(time.Second * 10))
if err != nil {
h.logger.Errorf("error getting logout requests: %v", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
h.logger.Debugf("received logout request: %#v", logoutRequest.Payload)
acceptLogoutRequest, err := h.adminClient.AcceptLogoutRequest(
admin.NewAcceptLogoutRequestParams().WithLogoutChallenge(challenge))
if err != nil {
h.logger.Errorf("error accepting logout: %v", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
w.Header().Set("Location", *acceptLogoutRequest.GetPayload().RedirectTo)
w.WriteHeader(http.StatusFound)
}
func NewLogoutHandler(logger *log.Logger, ctx context.Context) *logoutHandler {
return &logoutHandler{
logger: logger,
adminClient: ctx.Value(CtxAdminClient).(*admin.Client),
}
}
type logoutSuccessHandler struct {
}
func (l *logoutSuccessHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
panic("implement me")
}
func NewLogoutSuccessHandler() *logoutSuccessHandler {
return &logoutSuccessHandler{}
}