Skip to content

Commit c758594

Browse files
feat: identities getting started (#2103)
* feat: identities getting started * chore: format * docs: update identities get-started * chore: format * docs: refine based on feedback * docs: fix image cut offs * chore: format * docs: test js example * chore: format * docs: test all walkthroughs and refacot examples * chore: format * chore: use consistent titles * chore: resolve feedback * chore: format * docs: pre-requisites and user assumptions * chore: remove secure Co-authored-by: Vincent <[email protected]> * chore: remove bold from texts Co-authored-by: Vincent <[email protected]> * chore: highlight technical tokens Co-authored-by: Vincent <[email protected]> * chore: remove unnecessary word Co-authored-by: Vincent <[email protected]> * chore: use reusable setup section * chore: test code snippets and resolve feedback * chore: format * chore: apply suggestions from code review * chore: format * chore: remove webauthn quickstart * chore: format * chore: format * chore: comment --------- Co-authored-by: Vincent <[email protected]>
1 parent 023f4ec commit c758594

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1741
-2
lines changed

docs/_common/get-started-setup.mdx

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Before starting, ensure you have:
2+
3+
1. An [Ory network account](https://console.ory.sh)
4+
2. Your Ory project id
5+
3. Your development environment set up with your framework of choice
Loading
Loading
884 KB
Loading
720 KB
Loading
84 KB
Loading
340 KB
Loading
38.8 KB
Loading
46.1 KB
Loading
169 KB
Loading
151 KB
Loading
245 KB
Loading
Loading
29.7 KB
Loading
24.5 KB
Loading
115 KB
Loading
71.6 KB
Loading
171 KB
Loading
71.5 KB
Loading
72.2 KB
Loading
35.8 KB
Loading
132 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// dashboard_handler.go
2+
package main
3+
4+
import (
5+
"encoding/json"
6+
"net/http"
7+
)
8+
9+
// dashboardHandler simply displays the session information
10+
func (app *App) dashboardHandler(writer http.ResponseWriter, request *http.Request) {
11+
// Get the session from context
12+
session, err := getSession(request.Context())
13+
if err != nil {
14+
http.Error(writer, err.Error(), http.StatusInternalServerError)
15+
return
16+
}
17+
18+
// Return the session data as JSON
19+
writer.Header().Set("Content-Type", "application/json")
20+
encoder := json.NewEncoder(writer)
21+
encoder.SetIndent("", " ")
22+
encoder.Encode(session)
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module go-start
2+
3+
go 1.24.0
4+
5+
require (
6+
github.com/ory/client-go v1.20.6 // indirect
7+
golang.org/x/oauth2 v0.29.0 // indirect
8+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/ory/client-go v1.20.6 h1:1oUH4y1N8YCgR292FGw+atimSUgafMMIV8sZb36dH5U=
2+
github.com/ory/client-go v1.20.6/go.mod h1:10sCeMADXhQ9GbGhgfSFfj9Pzpnue/ZAVJFSwy/L1FU=
3+
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
4+
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"net/http"
6+
)
7+
8+
// LoginHandler handles the /login route
9+
func (app *App) loginHandler(writer http.ResponseWriter, request *http.Request) {
10+
// Get cookies from the request
11+
cookies := request.Header.Get("Cookie")
12+
13+
// Try to verify session with Ory
14+
session, response, err := app.ory.FrontendAPI.ToSession(request.Context()).Cookie(cookies).Execute()
15+
16+
// If there's an error or session is not active, redirect to login UI
17+
if err != nil || (err == nil && !*session.Active) {
18+
http.Redirect(writer, request, app.tunnelUrl+"/self-service/login/browser", http.StatusSeeOther)
19+
return
20+
}
21+
22+
// If session is valid, send the session data as JSON response
23+
writer.Header().Set("Content-Type", "application/json")
24+
writer.WriteHeader(http.StatusOK)
25+
// Use io.Copy to copy the response body to the writer
26+
io.Copy(writer, response.Body)
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"net/http"
6+
)
7+
8+
// LogoutHandler handles the /logout route
9+
func (app *App) logoutHandler(writer http.ResponseWriter, request *http.Request) {
10+
// Get cookies from the request
11+
cookies := request.Header.Get("Cookie")
12+
13+
// Create a logout flow
14+
logoutFlow, _, err := app.ory.FrontendAPI.CreateBrowserLogoutFlow(request.Context()).
15+
Cookie(cookies).
16+
Execute()
17+
18+
if err != nil {
19+
log.Printf("Error creating logout flow: %v", err)
20+
// Redirect to home page if there's an error
21+
http.Redirect(writer, request, "/", http.StatusSeeOther)
22+
return
23+
}
24+
25+
// Redirect to the logout URL
26+
http.Redirect(writer, request, logoutFlow.LogoutUrl, http.StatusSeeOther)
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"os"
7+
8+
ory "github.com/ory/client-go"
9+
)
10+
11+
// App holds application state
12+
type App struct {
13+
ory *ory.APIClient
14+
tunnelUrl string
15+
}
16+
17+
func main() {
18+
oryClient, baseUrl := ConfigureOryClient()
19+
20+
// Initialize application
21+
app := &App{
22+
ory: oryClient,
23+
tunnelUrl: baseUrl,
24+
}
25+
26+
// Setup routes
27+
mux := http.NewServeMux()
28+
mux.HandleFunc("/login", app.loginHandler)
29+
mux.HandleFunc("/logout", app.logoutHandler)
30+
mux.HandleFunc("/refresh-session", app.refreshSessionHandler)
31+
mux.Handle("/", app.sessionMiddleware(app.dashboardHandler))
32+
33+
// Get port from environment or use default
34+
port := os.Getenv("PORT")
35+
if port == "" {
36+
port = "3000"
37+
}
38+
39+
// Print tunnel command for convenience
40+
fmt.Printf("Starting server on port %s. Use tunnel with:\n", port)
41+
fmt.Printf("npx @ory/cli tunnel --dev http://localhost:%s\n", port)
42+
43+
// Start the server
44+
err := http.ListenAndServe(":"+port, mux)
45+
if err != nil {
46+
fmt.Printf("Could not start server: %s\n", err)
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"log"
7+
"net/http"
8+
9+
ory "github.com/ory/client-go"
10+
)
11+
12+
func (app *App) sessionMiddleware(next http.HandlerFunc) http.HandlerFunc {
13+
return func(writer http.ResponseWriter, request *http.Request) {
14+
log.Printf("Checking authentication status\n")
15+
16+
// Pass cookies to Ory's ToSession endpoint
17+
cookies := request.Header.Get("Cookie")
18+
19+
// Verify session with Ory
20+
session, _, err := app.ory.FrontendAPI.ToSession(request.Context()).Cookie(cookies).Execute()
21+
22+
// Redirect to login if session doesn't exist or is inactive
23+
if err != nil || (err == nil && !*session.Active) {
24+
log.Printf("No active session, redirecting to login\n")
25+
// Redirect to the login page
26+
http.Redirect(writer, request, app.tunnelUrl+"/self-service/login/browser", http.StatusSeeOther)
27+
return
28+
}
29+
// highlight-start
30+
if *session.AuthenticatorAssuranceLevel != "aal2" {
31+
http.Redirect(writer, request, app.tunnelUrl+"/self-service/login/browser?aal=aal2", http.StatusSeeOther)
32+
return
33+
}
34+
// highlight-end
35+
36+
// Add session to context for the handler
37+
ctx := withSession(request.Context(), session)
38+
next.ServeHTTP(writer, request.WithContext(ctx))
39+
}
40+
}
41+
42+
func withSession(ctx context.Context, v *ory.Session) context.Context {
43+
return context.WithValue(ctx, "req.session", v)
44+
}
45+
46+
func getSession(ctx context.Context) (*ory.Session, error) {
47+
session, ok := ctx.Value("req.session").(*ory.Session)
48+
if !ok || session == nil {
49+
return nil, errors.New("session not found in context")
50+
}
51+
return session, nil
52+
}
53+
54+
// Dashboard page protected by middleware
55+
mux.Handle("/", app.sessionMiddleware(app.dashboardHandler))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"log"
7+
"net/http"
8+
9+
ory "github.com/ory/client-go"
10+
)
11+
12+
func (app *App) sessionMiddleware(next http.HandlerFunc) http.HandlerFunc {
13+
return func(writer http.ResponseWriter, request *http.Request) {
14+
log.Printf("Checking authentication status\n")
15+
16+
// Pass cookies to Ory's ToSession endpoint
17+
cookies := request.Header.Get("Cookie")
18+
19+
// Verify session with Ory
20+
session, _, err := app.ory.FrontendAPI.ToSession(request.Context()).Cookie(cookies).Execute()
21+
22+
// Redirect to login if session doesn't exist or is inactive
23+
if err != nil || (err == nil && !*session.Active) {
24+
log.Printf("No active session, redirecting to login\n")
25+
// Redirect to the login page
26+
http.Redirect(writer, request, app.tunnelUrl+"/self-service/login/browser", http.StatusSeeOther)
27+
return
28+
}
29+
30+
// Add session to context for the handler
31+
ctx := withSession(request.Context(), session)
32+
next.ServeHTTP(writer, request.WithContext(ctx))
33+
}
34+
}
35+
36+
func withSession(ctx context.Context, v *ory.Session) context.Context {
37+
return context.WithValue(ctx, "req.session", v)
38+
}
39+
40+
func getSession(ctx context.Context) (*ory.Session, error) {
41+
session, ok := ctx.Value("req.session").(*ory.Session)
42+
if !ok || session == nil {
43+
return nil, errors.New("session not found in context")
44+
}
45+
return session, nil
46+
}
47+
48+
// Dashboard page protected by middleware
49+
mux.Handle("/", app.sessionMiddleware(app.dashboardHandler))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package main
2+
3+
import (
4+
"os"
5+
6+
ory "github.com/ory/client-go"
7+
)
8+
9+
// ConfigureOryClient sets up the Ory client for local development with tunnel
10+
func ConfigureOryClient() (*ory.APIClient, string) {
11+
baseUrl := os.Getenv("ORY_SDK_URL")
12+
13+
// Configure Ory SDK
14+
configuration := ory.NewConfiguration()
15+
configuration.Servers = ory.ServerConfigurations{{URL: baseUrl}}
16+
17+
// Create and return client
18+
return ory.NewAPIClient(configuration), baseUrl
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// refresh_handler.go
2+
package main
3+
4+
import (
5+
"net/http"
6+
)
7+
8+
// RefreshSessionHandler handles the /refresh-session route
9+
func (app *App) refreshSessionHandler(writer http.ResponseWriter, request *http.Request) {
10+
// Redirect to Ory login UI with refresh=true parameter
11+
http.Redirect(writer, request, app.tunnelUrl+"/self-service/login/browser?refresh=true", http.StatusSeeOther)
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"net/http"
6+
)
7+
8+
// SignUpHandler handles the /signup route
9+
func (app *App) signUpHandler(writer http.ResponseWriter, request *http.Request) {
10+
// Get cookies from the request
11+
cookies := request.Header.Get("Cookie")
12+
13+
// Try to verify session with Ory
14+
session, response, err := app.ory.FrontendAPI.ToSession(request.Context()).Cookie(cookies).Execute()
15+
16+
// If there's an error or session is not active, redirect to login UI
17+
if err != nil || (err == nil && !*session.Active) {
18+
http.Redirect(writer, request, app.tunnelUrl+"/self-service/registration/browser", http.StatusSeeOther)
19+
return
20+
}
21+
22+
// If session is valid, send the session data as JSON response
23+
writer.Header().Set("Content-Type", "application/json")
24+
writer.WriteHeader(http.StatusOK)
25+
// Use io.Copy to copy the response body to the writer
26+
io.Copy(writer, response.Body)
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
app.get("/", (req, res) => {
2+
ory
3+
.toSession({ cookie: req.header("cookie") })
4+
.then((data) => res.json(data))
5+
.catch(() =>
6+
res.redirect(`${process.env.ORY_SDK_URL}/self-service/login/browser`),
7+
)
8+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Create logout route
2+
app.get("/logout", async (req, res) => {
3+
try {
4+
// Create a logout flow
5+
const { logout_url } = await ory.createBrowserLogoutFlow({
6+
cookie: req.header("cookie"),
7+
})
8+
// Redirect to logout URL
9+
res.redirect(logout_url)
10+
} catch (err) {
11+
res.redirect("/")
12+
}
13+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const requireAuth = async (req, res, next) => {
2+
try {
3+
const session = await ory.toSession({ cookie: req.header("cookie") })
4+
// highlight-start
5+
if (session.authenticator_assurance_level === "aal2") {
6+
req.session = session
7+
next()
8+
} else {
9+
res.redirect(
10+
`${process.env.ORY_SDK_URL}/self-service/login/browser?aal=aal2`,
11+
)
12+
}
13+
// highlight-end
14+
} catch (error) {
15+
res.redirect(`${process.env.ORY_SDK_URL}/self-service/login/browser`)
16+
}
17+
}
18+
19+
app.get("/", requireAuth, (req, res) => {
20+
res.json(req.session.identity.traits) // { email: 'newtestuser@gmail.com' }
21+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const requireAuth = async (req, res, next) => {
2+
try {
3+
const session = await ory.toSession({ cookie: req.header("cookie") })
4+
req.session = session
5+
next()
6+
} catch (error) {
7+
res.redirect(`${process.env.ORY_SDK_URL}/self-service/login/browser`)
8+
}
9+
}
10+
11+
app.get("/", requireAuth, (req, res) => {
12+
res.json(req.session.identity.traits) // { email: 'newtestuser@gmail.com' }
13+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
app.get("/refresh-session", async (req, res) => {
2+
// Redirect to login with refresh=true parameter
3+
res.redirect(`${baseUrl}/ui/login?refresh=true`)
4+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Configuration, FrontendApi } from "@ory/client-fetch"
2+
3+
const baseUrl = process.env.ORY_SDK_URL || "http://localhost:4000"
4+
const ory = new FrontendApi(
5+
new Configuration({
6+
basePath: baseUrl,
7+
}),
8+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
app.get("/", (req, res) => {
2+
ory
3+
.toSession({ cookie: req.header("cookie") })
4+
.then((data) => res.json(data))
5+
.catch(() =>
6+
res.redirect(
7+
`${process.env.ORY_SDK_URL}/self-service/registration/browser`,
8+
),
9+
)
10+
})

0 commit comments

Comments
 (0)