diff options
author | Max Magorsch <arzano@gentoo.org> | 2020-12-08 01:21:04 +0000 |
---|---|---|
committer | Max Magorsch <arzano@gentoo.org> | 2020-12-08 01:21:04 +0000 |
commit | ba76c05ceca6a7879678873f360cdaf575f0f493 (patch) | |
tree | 597f2ee142ca4e57f1daffd29286e533c10a397a /pkg/app/handler/auth/handlers.go | |
download | go-gentoo-ba76c05ceca6a7879678873f360cdaf575f0f493.tar.gz go-gentoo-ba76c05ceca6a7879678873f360cdaf575f0f493.tar.bz2 go-gentoo-ba76c05ceca6a7879678873f360cdaf575f0f493.zip |
Initial version
Signed-off-by: Max Magorsch <arzano@gentoo.org>
Diffstat (limited to 'pkg/app/handler/auth/handlers.go')
-rw-r--r-- | pkg/app/handler/auth/handlers.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/pkg/app/handler/auth/handlers.go b/pkg/app/handler/auth/handlers.go new file mode 100644 index 0000000..8e79959 --- /dev/null +++ b/pkg/app/handler/auth/handlers.go @@ -0,0 +1,101 @@ +package auth + +import ( + "crypto/rand" + "encoding/base64" + "encoding/json" + "go-gentoo/pkg/config" + "go-gentoo/pkg/models" + "golang.org/x/oauth2" + "net/http" + "net/url" +) + +func Login(w http.ResponseWriter, r *http.Request) { + b := make([]byte, 16) + rand.Read(b) + + state := base64.URLEncoding.EncodeToString(b) + + session, _ := CookieStore.Get(r, config.SessionStoreKey()) + session.Values["state"] = state + session.Save(r, w) + + url := Oauth2Config.AuthCodeURL(state) + http.Redirect(w, r, url, http.StatusFound) +} + +func Callback(w http.ResponseWriter, r *http.Request) { + session, err := CookieStore.Get(r, config.SessionStoreKey()) + + if err != nil { + http.Error(w, "state did not match", http.StatusBadRequest) + return + } + + if r.URL.Query().Get("state") != session.Values["state"] { + http.Error(w, "state did not match", http.StatusBadRequest) + return + } + + oauth2Token, err := Oauth2Config.Exchange(Ctx, r.URL.Query().Get("code")) + if err != nil { + http.Error(w, "Failed to exchange token: "+err.Error(), http.StatusInternalServerError) + return + } + rawIDToken, ok := oauth2Token.Extra("id_token").(string) + if !ok { + http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError) + return + } + idToken, err := Verifier.Verify(Ctx, rawIDToken) + if err != nil { + http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError) + return + } + + resp := struct { + OAuth2Token *oauth2.Token + IDTokenClaims *json.RawMessage // ID Token payload is just JSON. + }{oauth2Token, new(json.RawMessage)} + + if err := idToken.Claims(&resp.IDTokenClaims); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + type Response struct { + GivenName string `json:"given_name"` + Username string `json:"preferred_username"` + Email string `json:"email"` + } + + var keycloakResponse Response + err = json.Unmarshal(*resp.IDTokenClaims, &keycloakResponse) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + session.Values["idToken"] = rawIDToken + session.Values["user"] = models.User{ + Email: keycloakResponse.Email, + RealName: keycloakResponse.GivenName, + UserName: keycloakResponse.Username, + Projects: nil, + } + err = session.Save(r, w) + + http.Redirect(w, r, "/", http.StatusFound) +} + +// http://www.gorillatoolkit.org/pkg/sessions#CookieStore.MaxAge +func Logout(w http.ResponseWriter, r *http.Request) { + session, err := CookieStore.Get(r, config.SessionStoreKey()) + if err != nil { + return + } + session.Options.MaxAge = -1 + session.Save(r, w) + http.Redirect(w, r, config.OIDConfigURL()+"/protocol/openid-connect/logout?redirect_uri="+url.QueryEscape(config.ApplicationURL()), 302) +} |