From 10ca63ce0ecfacdbd96d0d0fdc54ae24d12453b2 Mon Sep 17 00:00:00 2001 From: zepatrik Date: Fri, 4 Oct 2024 12:37:28 +0200 Subject: [PATCH 1/3] chore: simplify go example app --- code-examples/protect-page-login/go/go.mod | 4 +- code-examples/protect-page-login/go/go.sum | 4 ++ .../protect-page-login/go/handler.go | 54 +++++++++++------ .../protect-page-login/go/index.html | 11 ---- code-examples/protect-page-login/go/main.go | 10 +++- .../protect-page-login/go/middleware.go | 59 +++++++++---------- docs/getting-started/_common/teaser.mdx | 4 +- docs/getting-started/integrate-auth/01_go.mdx | 10 +--- 8 files changed, 81 insertions(+), 75 deletions(-) delete mode 100644 code-examples/protect-page-login/go/index.html diff --git a/code-examples/protect-page-login/go/go.mod b/code-examples/protect-page-login/go/go.mod index bd6612ada..3e122d011 100644 --- a/code-examples/protect-page-login/go/go.mod +++ b/code-examples/protect-page-login/go/go.mod @@ -2,6 +2,6 @@ module github.com/ory/docs/code-examples/go go 1.17 -require github.com/ory/client-go v1.11.7 +require github.com/ory/client-go v1.15.5 -require golang.org/x/oauth2 v0.21.0 // indirect +require golang.org/x/oauth2 v0.23.0 // indirect diff --git a/code-examples/protect-page-login/go/go.sum b/code-examples/protect-page-login/go/go.sum index 62861d180..b0ac405b3 100644 --- a/code-examples/protect-page-login/go/go.sum +++ b/code-examples/protect-page-login/go/go.sum @@ -5,6 +5,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/ory/client-go v1.11.7 h1:Ci/St58ItRRzBMKpCa60oUm8vZKvh4jAiRl1YA9I17A= github.com/ory/client-go v1.11.7/go.mod h1:LbWxa47gEulUk3912cIl+yVUa0hboRGrpGTYwdcSAJg= +github.com/ory/client-go v1.15.5 h1:WZ2p9O2H8J6vMa6e1oj0+RA9GQt4Laa7sY4rA0/D7wk= +github.com/ory/client-go v1.15.5/go.mod h1:kF9vH8mfpLJvgJus6dOjSXZ6KoswiwwcJ25hP7w2O8k= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -17,6 +19,8 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8 golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/code-examples/protect-page-login/go/handler.go b/code-examples/protect-page-login/go/handler.go index 5252d58cd..77c26b71c 100644 --- a/code-examples/protect-page-login/go/handler.go +++ b/code-examples/protect-page-login/go/handler.go @@ -9,22 +9,42 @@ import ( "net/http" ) -func (app *App) dashboardHandler() http.HandlerFunc { - return func(writer http.ResponseWriter, request *http.Request) { - tmpl, err := template.New("index.html").ParseFiles("index.html") - if err != nil { - http.Error(writer, err.Error(), http.StatusInternalServerError) - return - } - session, err := json.Marshal(getSession(request.Context())) - if err != nil { - http.Error(writer, err.Error(), http.StatusInternalServerError) - return - } - err = tmpl.ExecuteTemplate(writer, "index.html", string(session)) - if err != nil { - http.Error(writer, err.Error(), http.StatusInternalServerError) - return - } +func (app *App) dashboardHandler(writer http.ResponseWriter, request *http.Request) { + session, err := getSession(request.Context()) + if err != nil { + http.Error(writer, err.Error(), http.StatusInternalServerError) + return + } + rawSession, err := json.Marshal(session) + if err != nil { + http.Error(writer, err.Error(), http.StatusInternalServerError) + return + } + err = dashboardTemplate.ExecuteTemplate(writer, "index.html", rawSession) + if err != nil { + http.Error(writer, err.Error(), http.StatusInternalServerError) + return + } +} + +var dashboardTemplate *template.Template + +func init() { + var err error + dashboardTemplate, err = template.New("index.html").Parse(` + + + Ory Network secured Go web app + + +

Dashboard

+
+

Your Session Data:

+ {{ . }} + + +`) + if err != nil { + panic(err) } } diff --git a/code-examples/protect-page-login/go/index.html b/code-examples/protect-page-login/go/index.html deleted file mode 100644 index 067d4c1b7..000000000 --- a/code-examples/protect-page-login/go/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - Ory Network secured Go web app - - -

Dashboard

-
-

Your Session Data:

- {{ . }} - - diff --git a/code-examples/protect-page-login/go/main.go b/code-examples/protect-page-login/go/main.go index da2f98f6a..d6e6adf51 100644 --- a/code-examples/protect-page-login/go/main.go +++ b/code-examples/protect-page-login/go/main.go @@ -4,6 +4,7 @@ package main import ( + "errors" "fmt" "net/http" "os" @@ -32,7 +33,7 @@ func main() { mux := http.NewServeMux() // dashboard - mux.Handle("/", app.sessionMiddleware(app.dashboardHandler())) + mux.Handle("/", app.sessionMiddleware(app.dashboardHandler)) port := os.Getenv("PORT") if port == "" { @@ -41,5 +42,10 @@ func main() { fmt.Printf("Application launched and running on http://127.0.0.1:%s\n", port) // start the server - http.ListenAndServe(":"+port, mux) + err := http.ListenAndServe(":"+port, mux) + if errors.Is(err, http.ErrServerClosed) { + fmt.Println("Server closed") + return + } + fmt.Printf("Could not start server: %s\n", err) } diff --git a/code-examples/protect-page-login/go/middleware.go b/code-examples/protect-page-login/go/middleware.go index e37708f57..1abde5c26 100644 --- a/code-examples/protect-page-login/go/middleware.go +++ b/code-examples/protect-page-login/go/middleware.go @@ -5,57 +5,52 @@ package main import ( "context" + "errors" "log" "net/http" ory "github.com/ory/client-go" ) -// save the cookies for any upstream calls to the Ory apis -func withCookies(ctx context.Context, v string) context.Context { - return context.WithValue(ctx, "req.cookies", v) -} - -func getCookies(ctx context.Context) string { - return ctx.Value("req.cookies").(string) -} - -// save the session to display it on the dashboard -func withSession(ctx context.Context, v *ory.Session) context.Context { - return context.WithValue(ctx, "req.session", v) -} - -func getSession(ctx context.Context) *ory.Session { - return ctx.Value("req.session").(*ory.Session) -} - func (app *App) sessionMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(writer http.ResponseWriter, request *http.Request) { log.Printf("handling middleware request\n") - // set the cookies on the ory client - var cookies string - - // this example passes all request.Cookies - // to `ToSession` function + // This example passes all request.Cookies to `ToSession` function. // - // However, you can pass only the value of - // ory_session_projectid cookie to the endpoint - cookies = request.Header.Get("Cookie") + // However, it is enough to pass only the value of the `ory_session_projectslug` cookie to the endpoint. + cookies := request.Header.Get("Cookie") + + // A native app would submit the session token instead of a cookie. + // You can look up session tokens the same way by using the `XSessionToken` setter on the `ToSession` function. - // check if we have a session + // Look up session. session, _, err := app.ory.FrontendAPI.ToSession(request.Context()).Cookie(cookies).Execute() - if (err != nil && session == nil) || (err == nil && !*session.Active) { - // this will redirect the user to the managed Ory Login UI + // Check if a session exists and if it is active. + // You could add your own logic here to check if the session is valid for the specific endpoint, e.g. using the `session.AuthenticatedAt` field. + if err != nil || (err == nil && !*session.Active) { + // redirect the user to the login UI, in this case we use the default browser flow http.Redirect(writer, request, "/.ory/self-service/login/browser", http.StatusSeeOther) return } - ctx := withCookies(request.Context(), cookies) - ctx = withSession(ctx, session) + // Add the session details to the context for handlers to access. + ctx := withSession(request.Context(), session) - // continue to the requested page (in our case the Dashboard) + // Continue to the next handler (the dashboard in the simple example). next.ServeHTTP(writer, request.WithContext(ctx)) return } } + +func withSession(ctx context.Context, v *ory.Session) context.Context { + return context.WithValue(ctx, "req.session", v) +} + +func getSession(ctx context.Context) (*ory.Session, error) { + session, ok := ctx.Value("req.session").(*ory.Session) + if !ok || session == nil { + return nil, errors.New("session not found in context") + } + return session, nil +} diff --git a/docs/getting-started/_common/teaser.mdx b/docs/getting-started/_common/teaser.mdx index e6577aca2..290f194e6 100644 --- a/docs/getting-started/_common/teaser.mdx +++ b/docs/getting-started/_common/teaser.mdx @@ -1,8 +1,8 @@ import VideoEmbed from "@site/src/components/VideoEmbed"

- This guide shows how to create a simple {props.framework} application and secure it with authentication powered by Ory. You can - use this guide with both Ory Network and self-hosted Ory software. + This guide shows how to create a simple {props.framework} application and secure it with authentication powered by Ory. The + guide provides the setup for using Ory Network, but the code can be used with both Ory Network and self-hosted Ory software.

This guide is perfect for you if: diff --git a/docs/getting-started/integrate-auth/01_go.mdx b/docs/getting-started/integrate-auth/01_go.mdx index 5bae1f542..9e07c305b 100644 --- a/docs/getting-started/integrate-auth/01_go.mdx +++ b/docs/getting-started/integrate-auth/01_go.mdx @@ -86,7 +86,7 @@ import middlewareGo from '!!raw-loader!../../../code-examples/protect-page-login As the final step, create a `Dashboard` page that's presented to signed-in users. This page diplays the user's session data. -1. Create the `dashboardHandler` that renders the page with the session data. Add this code to the `handler.go` file: +To create the `dashboardHandler` that renders the page with the session data, add this code to the `handler.go` file: ```mdx-code-block import handlerGo from '!!raw-loader!../../../code-examples/protect-page-login/go/handler.go' @@ -94,14 +94,6 @@ import handlerGo from '!!raw-loader!../../../code-examples/protect-page-login/go {handlerGo} ``` -2. To present the data to the user, create the `Dashboard` HTML page. Add this code to the `index.html` file: - -```mdx-code-block -import index from '!!raw-loader!../../../code-examples/protect-page-login/go/index.html' - -{index} -``` - ## Test your application With all of the pieces in place, it's time to test your application. Follow these steps: From e36f4717fdb2e7037b01c147993649b273152d9f Mon Sep 17 00:00:00 2001 From: zepatrik Date: Fri, 4 Oct 2024 13:36:34 +0200 Subject: [PATCH 2/3] chore: go mod tidy --- code-examples/protect-page-login/go/go.sum | 5 ----- 1 file changed, 5 deletions(-) diff --git a/code-examples/protect-page-login/go/go.sum b/code-examples/protect-page-login/go/go.sum index b0ac405b3..725238c3a 100644 --- a/code-examples/protect-page-login/go/go.sum +++ b/code-examples/protect-page-login/go/go.sum @@ -3,8 +3,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/ory/client-go v1.11.7 h1:Ci/St58ItRRzBMKpCa60oUm8vZKvh4jAiRl1YA9I17A= -github.com/ory/client-go v1.11.7/go.mod h1:LbWxa47gEulUk3912cIl+yVUa0hboRGrpGTYwdcSAJg= github.com/ory/client-go v1.15.5 h1:WZ2p9O2H8J6vMa6e1oj0+RA9GQt4Laa7sY4rA0/D7wk= github.com/ory/client-go v1.15.5/go.mod h1:kF9vH8mfpLJvgJus6dOjSXZ6KoswiwwcJ25hP7w2O8k= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -16,9 +14,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 2a2a700f659f5dc5ac1b7941d55a2df6c8c67501 Mon Sep 17 00:00:00 2001 From: zepatrik Date: Mon, 7 Oct 2024 12:08:21 +0200 Subject: [PATCH 3/3] fix: JSON rendering --- code-examples/protect-page-login/go/handler.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/code-examples/protect-page-login/go/handler.go b/code-examples/protect-page-login/go/handler.go index 77c26b71c..216dbf9c6 100644 --- a/code-examples/protect-page-login/go/handler.go +++ b/code-examples/protect-page-login/go/handler.go @@ -4,23 +4,31 @@ package main import ( + "bytes" "encoding/json" "html/template" "net/http" ) func (app *App) dashboardHandler(writer http.ResponseWriter, request *http.Request) { + // Get the session from the context. It was added to the context by the sessionMiddleware. session, err := getSession(request.Context()) if err != nil { http.Error(writer, err.Error(), http.StatusInternalServerError) return } - rawSession, err := json.Marshal(session) - if err != nil { + + // Encode the session data as pretty JSON. + buffer := &bytes.Buffer{} + encoder := json.NewEncoder(buffer) + encoder.SetIndent("", " ") + if err := encoder.Encode(session); err != nil { http.Error(writer, err.Error(), http.StatusInternalServerError) return } - err = dashboardTemplate.ExecuteTemplate(writer, "index.html", rawSession) + + // Render the dashboard template with the session data. + err = dashboardTemplate.ExecuteTemplate(writer, "index.html", buffer.String()) if err != nil { http.Error(writer, err.Error(), http.StatusInternalServerError) return