<@U04UQ68083H> When using Ory Sessions, what is me...
# ory-copilot
c
@chilly-king-10285 When using Ory Sessions, what is meant by: “Ory checks for both the cookie and the token, which means that your API must handle both Ory Session Cookies and Ory Session Tokens:”
b
A message from kapa.ai
This statement refers to how Ory handles authentication when checking for valid sessions. Ory's security model supports two different session formats: 1. Ory Session Cookies: Used for browser-based applications (like web apps). When a user authenticates through a browser, Ory issues a session cookie that's automatically included in subsequent requests. 2. Ory Session Tokens: Used for non-browser clients (like mobile apps, desktop applications, or API clients). These are explicitly passed in requests rather than being automatically managed by a browser. When your API or application checks if a user is authenticated by calling the
/sessions/whoami
endpoint, Ory will look for authentication in multiple places: - It checks for an Ory Session Cookie in the
Cookie
HTTP header - It checks for an Ory Session Token in the
X-Session-Token
HTTP header - It checks for an Ory Session Token in the
Authorization: bearer <token>
HTTP header This means your API needs to be prepared to handle both authentication methods, depending on what type of client is connecting to your service. For browser clients, you'll typically forward cookies, while for native applications, you'll need to handle the session token. As the documentation states: > This endpoint authenticates users by checking: > - if the
Cookie
HTTP header was set containing an Ory Kratos Session Cookie; > - if the
Authorization: bearer <ory-session-token>
HTTP header was set with a valid Ory Kratos Session Token; > - if the
X-Session-Token
HTTP header was set with a valid Ory Kratos Session Token. [Ory API Reference](https://www.ory.sh/docs/reference/api) For server-side applications, you would typically forward the cookie header:
Copy code
js router.get('/protected-endpoint', async function (req, res) {   const session = await client.toSession(undefined, req.header('cookie'))   console.log(session) })
For non-browser applications, you would use the session token:
Copy code
js const session = await client.toSession("the-session-token") console.log(session)
This dual approach allows Ory to provide a secure authentication system that works across different types of applications while maintaining the same security model.
c
use golang as examples
@chilly-king-10285 Use golang for examples
b
A message from kapa.ai
I'll provide Go examples for working with Ory Sessions, showing how to handle both Ory Session Cookies and Ory Session Tokens. ## Checking Sessions in Go ### Using Ory Session Cookies (Browser Applications) For browser-based applications, you can check the session using the cookie that's automatically sent with the request:
Copy code
go package main  import (  "context"  "fmt"  "os"   client "<http://github.com/ory/kratos-client-go|github.com/ory/kratos-client-go>" )  func main() {  configuration := client.NewConfiguration()  configuration.Servers = []client.ServerConfiguration{   {    URL: "<http://127.0.0.1:4433>", // Kratos Public API   },  }  apiClient := client.NewAPIClient(configuration)    // Get the cookie from the request header  cookie := request.Header.Get("Cookie")    // Pass the cookie to the toSession method  resp, r, err := apiClient.FrontendApi.ToSession(context.Background()).Cookie(cookie).Execute()  if err != nil {   fmt.Fprintf(os.Stderr, "Error when calling `FrontendApi.ToSession``: %v\n", err)   fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)  }    // Use the session data  fmt.Fprintf(os.Stdout, "Traits: %v\n", resp.Identity.Traits) }
### Using Ory Session Tokens (Native Applications) For native applications, you would use the session token:
Copy code
go package frontend  import (  "context"  "fmt"  "os"   "<http://github.com/ory/client-go|github.com/ory/client-go>" )  type oryMiddleware struct {  ory *ory.APIClient }  func init() {  cfg := client.NewConfiguration()  cfg.Servers = client.ServerConfigurations{   {URL: fmt.Sprintf("<https://%s.projects.oryapis.com>", os.Getenv("ORY_PROJECT_SLUG"))},  }   ory = client.NewAPIClient(cfg) }  func CheckSession(ctx context.Context, sessionToken string) (session *client.Session, err error) {  session, _, err = ory.FrontendApi.ToSession(ctx).   XSessionToken(sessionToken).   Execute()  if err != nil {   // error checking the session, for example due to expired token provided   return nil, err  }   return session, nil }
### Middleware Example for Web Applications Here's a more complete middleware example that checks for valid sessions in a web application:
Copy code
go package main  import (  "context"  "errors"  "log"  "net/http"   ory "<http://github.com/ory/client-go|github.com/ory/client-go>" )  func (app *App) sessionMiddleware(next http.HandlerFunc) http.HandlerFunc {  return func(writer http.ResponseWriter, request *http.Request) {   log.Printf("handling middleware request\n")    // This example passes all request.Cookies to `ToSession` function.   cookies := request.Header.Get("Cookie")    // Look up session.   session, _, err := app.ory.FrontendAPI.ToSession(request.Context()).Cookie(cookies).Execute()   // Check if a session exists and if it is active.   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   }    // Add the session details to the context for handlers to access.   ctx := withSession(request.Context(), session)    // 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 }
This middleware checks for a valid session using the cookie from the request. If the session is valid, it adds the session to the request context and continues to the next handler. If the session is not valid, it redirects the user to the login page. [Integrate authentication into Go](https://www.ory.sh/docs/getting-started/integrate-auth/go#validate-and-login) These examples demonstrate how to handle both Ory Session Cookies and Ory Session Tokens in Go applications, allowing you to authenticate users regardless of whether they're using a browser or a native application.
c
@chilly-king-10285 Does the
err
that may result from the
FrontendAPI.ToSession
function indicate an invalid session, or just an error in obtaining the session?
b
A message from kapa.ai
The
err
returned from the
FrontendAPI.ToSession
function can indicate both an invalid session and errors in obtaining the session. Let me explain the different scenarios: When calling
ToSession
, an error can occur in these main cases: 1. Invalid or expired session: If the session cookie or token is invalid, expired, or doesn't exist, the API will return a 401 Unauthorized error. This is the most common case and indicates that the user is not authenticated. 2. Insufficient authentication level: If the session exists but doesn't meet the required authentication assurance level (AAL), a 403 Forbidden error is returned. This happens when a user has authenticated with a lower level than required (e.g., only password when both password and second factor are required). 3. Technical errors: These could be network issues, server problems, or other technical difficulties in making the API call. From the documentation, we can see that the error response includes an
id
field that helps identify the specific error: - `session_inactive`: No active session was found in the request - `session_aal2_required`: An active session was found but it doesn't fulfill the required Authenticator Assurance Level [Ory API Reference](https://www.ory.sh/docs/kratos/reference/api) Here's how you might handle these errors in Go:
Copy code
go session, r, err := app.ory.FrontendAPI.ToSession(request.Context()).Cookie(cookies).Execute() if err != nil {     // Check if this is an authentication error (401)     if r != nil && r.StatusCode == 401 {         // User is not authenticated         http.Redirect(writer, request, "/.ory/self-service/login/browser", http.StatusSeeOther)         return     } else if r != nil && r.StatusCode == 403 {         // User is authenticated but needs to complete additional authentication steps         // e.g., second factor authentication         http.Redirect(writer, request, "/.ory/self-service/login/browser?aal=aal2", http.StatusSeeOther)         return     } else {         // Some other error occurred (network, server, etc.)         log.Printf("Error checking session: %v", err)         http.Error(writer, "Internal Server Error", http.StatusInternalServerError)         return     } }  // Session is valid and active if !*session.Active {     // This is a rare case where we got a session but it's not active     http.Redirect(writer, request, "/.ory/self-service/login/browser", http.StatusSeeOther)     return }  // Continue with valid session
This approach allows you to distinguish between authentication errors (invalid session) and technical errors, and handle each appropriately in your application.