package main import ( "context" "crypto/rand" "encoding/base64" "fmt" "log" "net/http" "github.com/coreos/go-oidc/v3/oidc" "golang.org/x/oauth2" ) const ( keycloakURL = "https://auth.cloud.osnawiki.de/realms/oidc-demo" clientID = "go-demo" clientSecret = "VEnWQP1oWCLVCnXB425OxihRj52wfpsisDz1krZlvnSsTpG8GL4v1egffHGDAvhOjZHCFQ4jd2OJ3rHfX2Ge3C" redirectURL = "https://oidc-demo.cloud.osnawiki.de/callback" ) var ( oauthConfig *oauth2.Config verifier *oidc.IDTokenVerifier ) func main() { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{ InsecureSkipVerify: true, } ctx := context.Background() // OIDC Discovery (.well-known/openid-configuration) provider, err := oidc.NewProvider(ctx, keycloakURL) if err != nil { log.Fatal(err) } verifier = provider.Verifier( &oidc.Config{ ClientID: clientID, }, ) oauthConfig = &oauth2.Config{ ClientID: clientID, ClientSecret: clientSecret, Endpoint: provider.Endpoint(), RedirectURL: redirectURL, Scopes: []string{ "openid", "profile", "email", }, } http.HandleFunc("/", home) http.HandleFunc("/login", login) http.HandleFunc("/callback", callback) http.HandleFunc("/logout", logout) log.Println("running :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } // Startet OIDC Login func login(w http.ResponseWriter, r *http.Request) { // CSRF-Schutz: State erzeugen state := randomString() http.SetCookie(w, &http.Cookie{ Name: "oidc_state", Value: state, Path: "/", }) url := oauthConfig.AuthCodeURL( state, ) http.Redirect(w, r, url, http.StatusFound) } // Callback von Keycloak func callback(w http.ResponseWriter, r *http.Request) { stateCookie, _ := r.Cookie("oidc_state") if stateCookie == nil || stateCookie.Value != r.URL.Query().Get("state") { http.Error(w, "invalid state", 400) return } token, err := oauthConfig.Exchange( r.Context(), r.URL.Query().Get("code"), ) if err != nil { http.Error(w, err.Error(), 500) return } rawIDToken, ok := token.Extra("id_token").(string) if !ok { http.Error(w, "missing id_token", 500) return } idToken, err := verifier.Verify( r.Context(), rawIDToken, ) if err != nil { http.Error(w, "invalid token", 500) return } // Userinformationen aus Token lesen var claims struct { Username string `json:"preferred_username"` Email string `json:"email"` } idToken.Claims(&claims) http.SetCookie(w, &http.Cookie{ Name: "user", Value: claims.Username, Path: "/", }) http.Redirect(w, r, "/", 302) } func home(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("user") if err != nil { fmt.Fprint(w, `