diff --git a/auth/auth.go b/auth/auth.go index e524f6a..bce99dd 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -1,18 +1,59 @@ package auth import ( + "crypto/rand" + "encoding/base64" "fmt" + "net/http" "astraltech.xyz/calendar/v2/webserver" + "golang.org/x/oauth2" ) +func generateState() (string, error) { + b := make([]byte, 32) + if _, err := rand.Read(b); err != nil { + return "", err + } + return base64.RawURLEncoding.EncodeToString(b), nil +} + func HandlePasswordAuth(authData webserver.PasswordAuthData) bool { fmt.Printf("%s, %s\n", authData.Username, authData.Password) return false } func HandleOAuth(authData webserver.OAuthAuthData) bool { - fmt.Printf("doing an OAuth") + state, err := generateState() + if err != nil { + http.Error(*authData.ResponseWriter, "Failed to generate state", http.StatusInternalServerError) + return false + } + verifier := oauth2.GenerateVerifier() + + http.SetCookie(*authData.ResponseWriter, &http.Cookie{ + Name: "oauth_state", + Value: state, + Path: "/", + MaxAge: 300, + HttpOnly: true, + SameSite: http.SameSiteLaxMode, + }) + + http.SetCookie(*authData.ResponseWriter, &http.Cookie{ + Name: "pkce_verifier", + Value: verifier, + Path: "/", + HttpOnly: true, + SameSite: http.SameSiteLaxMode, + }) + + url := OAuthConfigs[0].AuthCodeURL( + state, + oauth2.S256ChallengeOption(verifier), + ) + http.Redirect(*authData.ResponseWriter, authData.Request, url, http.StatusFound) + return false } diff --git a/auth/oauth.go b/auth/oauth.go index f02bdc2..06a0fb5 100644 --- a/auth/oauth.go +++ b/auth/oauth.go @@ -1,22 +1,31 @@ package auth import ( + "context" + + "github.com/coreos/go-oidc/v3/oidc" "golang.org/x/oauth2" ) -var oauthConfigs []oauth2.Config +var OAuthConfigs []oauth2.Config func CreateTestOAuth() { - oauthEndpoint := oauth2.Endpoint{ - AuthURL: "https://account.astraltech.xyz/application/o/authorize/", - TokenURL: "https://account.astraltech.xyz/application/o/token/", + ctx := context.Background() + + provider, err := oidc.NewProvider(ctx, "https://account.astraltech.xyz/application/o/stalwart/") + if err != nil { + panic(err) } oauthConfig := oauth2.Config{ ClientID: "stalwart-webui", - Scopes: []string{"openid", "profile", "email"}, - Endpoint: oauthEndpoint, RedirectURL: "http://localhost:8080/callback", + Endpoint: provider.Endpoint(), + Scopes: []string{ + oidc.ScopeOpenID, + "profile", + "email", + }, } - oauthConfigs = append(oauthConfigs, oauthConfig) + OAuthConfigs = append(OAuthConfigs, oauthConfig) } diff --git a/auth/oauth_callback.go b/auth/oauth_callback.go index 4621ebe..98379fe 100644 --- a/auth/oauth_callback.go +++ b/auth/oauth_callback.go @@ -1,8 +1,11 @@ package auth -import "net/http" +import ( + "fmt" + "net/http" +) // this is usually served at /callback func OAuthCallback(w http.ResponseWriter, r *http.Request) { - + fmt.Printf("Getting my OAuth callback") } diff --git a/go.mod b/go.mod index a232a13..30c5a96 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,7 @@ go 1.26.1 require ( github.com/arran4/golang-ical v0.3.5 // indirect + github.com/coreos/go-oidc/v3 v3.20.0 // indirect + github.com/go-jose/go-jose/v4 v4.1.4 // indirect golang.org/x/oauth2 v0.36.0 // indirect ) diff --git a/go.sum b/go.sum index 3faf480..8e3801d 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,8 @@ github.com/arran4/golang-ical v0.3.5 h1:bbz6ld4dC+MmCKiFfOd6SkmIGnhNMBACZ485ULh7p9A= github.com/arran4/golang-ical v0.3.5/go.mod h1:OnguFgjN0Hmx8jzpmWcC+AkHio94ujmLHKoaef7xQh8= +github.com/coreos/go-oidc/v3 v3.20.0 h1:EtE0WIBHk03N+DqGkY4+UONzzZHk7amKt6IyNd7OsZE= +github.com/coreos/go-oidc/v3 v3.20.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= +github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= +github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= diff --git a/main/main.go b/main/main.go index 5162cd3..6b4be94 100644 --- a/main/main.go +++ b/main/main.go @@ -7,6 +7,7 @@ import ( ) func main() { + auth.CreateTestOAuth() read_config() caldav.InitDavClient(serverConfig.URL) diff --git a/webserver/login_page.go b/webserver/login_page.go index 6f9bc4c..0a8f4e8 100644 --- a/webserver/login_page.go +++ b/webserver/login_page.go @@ -25,8 +25,8 @@ type PasswordAuthData struct { } type OAuthAuthData struct { - Username string - Password string + ResponseWriter *http.ResponseWriter + Request *http.Request } type CustomizableLoginData struct { @@ -62,7 +62,10 @@ func loginHandler(w http.ResponseWriter, r *http.Request) { tmpl.Execute(w, LoginPageData{IsHiddenClassList: "", LoginData: LoginPageDataCustomizations}) } } else { - auth_success := LoginPageDataCustomizations.AuthRequestFunction(AuthStyleOAuth, OAuthAuthData{}) + auth_success := LoginPageDataCustomizations.AuthRequestFunction(AuthStyleOAuth, OAuthAuthData{ + ResponseWriter: &w, + Request: r, + }) if auth_success == false { tmpl.Execute(w, LoginPageData{IsHiddenClassList: "", LoginData: LoginPageDataCustomizations}) } diff --git a/webserver/pages/login_page.html b/webserver/pages/login_page.html index 3af1304..7155637 100644 --- a/webserver/pages/login_page.html +++ b/webserver/pages/login_page.html @@ -23,13 +23,13 @@

- +

- +