Refactor app, implement logout
This commit is contained in:
parent
ce1fac0e68
commit
27e225795c
14 changed files with 647 additions and 349 deletions
|
@ -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
20
idp/handlers/error.go
Normal 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{}
|
||||
}
|
|
@ -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
58
idp/handlers/logout.go
Normal 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{}
|
||||
}
|
Reference in a new issue