Files
query-orchestration/cmd/cognito_test/cognitotest
2025-03-28 18:00:48 -07:00
..
2025-03-28 12:55:55 -07:00
2025-03-28 18:00:48 -07:00

Cognito Auth Test Harness

This directory contains a test harness for validating AWS Cognito authentication and authorization with Go and the Echo web framework. It demonstrates a complete OAuth 2.0 flow with role-based access control (RBAC). It is temporary and will go away once the final middleware is in place.

Features

  • Complete OAuth 2.0 authentication flow with AWS Cognito
  • Role-based access control (RBAC) for API endpoints
  • JWT token validation with signature verification
  • Efficient JWKS caching to minimize external requests
  • Debug mode for token inspection

Setup

Prerequisites

  • Go 1.18 or higher
  • AWS Cognito User Pool with configured app client
  • Test user(s) in the Cognito User Pool with assigned groups

Environment Variables

Set the following environment variables before running the application:

export COGNITO_CLIENT_ID="552cqkf3640t39ncehkmgpce31"
export COGNITO_CLIENT_SECRET="your-client-secret"
export COGNITO_DOMAIN="us-east-21y6po8rr8.auth.us-east-2.amazoncognito.com"
export COGNITO_USER_POOL_ID="us-east-2_1y6po8rR8"
export AWS_REGION="us-east-2"

# Optional: Enable debug mode to see token details
export DEBUG="true"

Running the Application

  1. Build and run the server:
go run main.go
  1. The server will start on http://localhost:8080

Testing the Authentication Flow

Step 1: Initial Login

  1. Open the following URL in your browser (update domain/client_id if different):
https://us-east-21y6po8rr8.auth.us-east-2.amazoncognito.com/login?client_id=552cqkf3640t39ncehkmgpce31&response_type=code&scope=email+openid+phone&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fquery
  1. Log in with your Cognito user credentials

  2. After successful authentication, Cognito will redirect to your local server (/query endpoint)

  3. You'll see a JSON response with:

    • Authentication status
    • User information (username, email)
    • User groups
    • JWT tokens (id_token and access_token)

Example response:

{
  "authenticated": true,
  "username": "testuser",
  "email": "user@example.com",
  "groups": ["uploaders", "querybuilders"],
  "id_token": "eyJhbGciOiJSUzI1NiIs...",
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Step 2: Testing Protected Endpoints

Use the obtained token to access protected endpoints:

  1. Copy the id_token value from the response

  2. Use it as a Bearer token in subsequent requests:

# Using curl to access a protected endpoint
curl -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." http://localhost:8080/users
  1. Test authorization with different endpoints:
Endpoint Required Groups
/users exporters
/users/:id exporters, querybuilders
/orders exporters
/reports/sales exporters, uploaders, querybuilders
/settings exporters
/query exporters
/api/inventory/update exporters, uploaders

Note. If you want to change the RBAC requirements for the server they are completely table driven.
The code where they are defined (in main()) looks like this. Feel free to change them and rerun.

	routePermissions := map[string][]string{
		"/users":                {"exporters"},
		"/users/:id":            {"exporters", "querybuilders"},
		"/orders":               {"exporters", "exporters"},
		"/reports/sales":        {"exporters", "uploaders", "querybuilders"},
		"/settings":             {"exporters"},
		"/query":                {"exporters", "querybuilders"}, // Only exporters can access /query
		"/api/inventory/update": {"exporters", "uploaders"},
	}

  1. If your user doesn't have the required group for an endpoint, you'll receive a 403 Forbidden response:
{
  "error": "Insufficient permissions",
  "message": "User doesn't have the required group membership",
  "username": "testuser",
  "groups": ["uploaders", "querybuilders"],
  "required_groups": ["exporters"]
}

Authentication Flow Explained

Initial Login (OAuth 2.0 Flow)

  1. User Authentication: User authenticates with Cognito's hosted UI
  2. Authorization Code: Cognito redirects to /query?code=... with an authorization code
  3. Token Exchange: The server exchanges this code for OAuth tokens by calling Cognito's token endpoint
  4. Token Verification: The server verifies the JWT token signature using Cognito's JWKS
  5. Group Verification: The server checks if the user belongs to the required groups for the /query endpoint 6. Note that /query is just a placeholder and will be changes to something like /login or /login/callback in the api server. This setting is set in cognito on the user pool.
  6. Response: If authorized, the server returns the tokens and user information; if not, it returns a 403 error

Subsequent API Requests

  1. Token Submission: Client includes the ID token as a Bearer token in the Authorization header
  2. Token Validation: Server validates the token's signature, expiration, and other claims
  3. Group Extraction: Server extracts the user's groups from the token
  4. Permission Check: Server checks if the user has any of the required groups for the requested endpoint
  5. Access Control: If authorized, the request proceeds to the handler; if not, a 403 error is returned

Advanced Features

JWKS Caching

The server caches the JSON Web Key Set (JWKS) used to verify token signatures, reducing the number of requests to AWS.

Debug Mode

Enable debug mode by setting the DEBUG environment variable to true. This will:

  • Log decoded token claims
  • Log raw tokens
  • Provide more verbose logging throughout the authentication process

Integration into Your Own Application

This test harness is for proving the design of the echo middleware before attempting integration:

  1. The TokenValidationMiddleware handles both authentication and authorization
  2. The route permissions map can be configured to match our application's security requirements
  3. The JWKS caching mechanism ensures efficient token validation