summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/app/handler/auth/handlers.go')
-rw-r--r--pkg/app/handler/auth/handlers.go101
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)
+}