{"id":27969189,"url":"https://github.com/future-architect/future-wru","last_synced_at":"2025-10-15T17:32:48.266Z","repository":{"id":57706072,"uuid":"396777848","full_name":"future-architect/future-wru","owner":"future-architect","description":"Identity Aware Proxy","archived":false,"fork":false,"pushed_at":"2021-08-16T12:13:04.000Z","size":764,"stargazers_count":21,"open_issues_count":0,"forks_count":4,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-07T21:08:51.178Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/future-architect.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-16T12:08:47.000Z","updated_at":"2025-05-05T22:34:12.000Z","dependencies_parsed_at":"2022-08-24T12:50:37.328Z","dependency_job_id":null,"html_url":"https://github.com/future-architect/future-wru","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/future-architect%2Ffuture-wru","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/future-architect%2Ffuture-wru/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/future-architect%2Ffuture-wru/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/future-architect%2Ffuture-wru/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/future-architect","download_url":"https://codeload.github.com/future-architect/future-wru/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252954409,"owners_count":21830905,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-07T21:08:56.124Z","updated_at":"2025-10-15T17:32:43.217Z","avatar_url":"https://github.com/future-architect.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WRU: who are you\n\n![wru logo](doc/logo-small.png)\n\nWRU is an identity aware reverse proxy/middleware for enterprise users.\nIt provides seamless authentication experience between development environemnt and production environment.\n\n## What is WRU for\n\n- For enterprise users\n\n  - Easy to inject users via CSV files on storage (local, AWS S3, GCP Cloud Storage)\n\n- Not For consumer service users\n\n  - It is not supporting creating user\n\n- For testing\n\n  - Inject user information from env vars/files. You can setup via Docker easily\n  - No password required (E2E test friendly)\n\n- For production\n  - It supports OpenID Connect, some SNS (Twitter and GitHub for now) to login.\n\n## Use as Reverse Proxy\n\n### Getting Started\n\nYou can get wru by \"go get\".\n\n```bash\n$ go get -u\tgithub.com/future-architect/future-wru/cmd/wru\n$ wru\nPort: 8000\nTLS: enabled\nDebug: false\nForward To:\n  / =\u003e http://localhost:8080 ()\nTwitter Login: OK\nGitHub Login: OK\nUsers (for Debug):\n  (User) 'test user 1'(user1) @ R\u0026D (scopes: admin, user, org:rd)\n  (User) 'test user 2'(user2) @ HR (scopes: user, org:hr)\nstarting wru server at https://localhost:8000\n```\n\n`wru` command doesn't have command line options. You can control it via environment variables.\n\n### WRU modes\n\nWRU has two modes. This absorbs the difference of usecases and\nyour web service always get only authorized requests.\n\n#### WRU for local development\n\n![dev-mode](doc/dialogs-dev-mode.png)\n\nSample configuration:\n\n- Launch at https://localhost:8000\n- Enable HTTPS by wru\n- A backend server is at http://localhost:8080\n- Two test users\n- Session storage is in-memory mode (turn off wru resets data)\n\n```bash\n$ export WRU_DEV_MODE=true\n$ export WRU_TLS_CERT=\"-----BEGIN CERTIFICATE-----\\naaaabbbbbcccccdddd....zzzz\\n-----END CERTIFICATE-----\"\n$ export WRU_TLS_KEY=\"-----BEGIN PRIVATE KEY-----\\nZZZZYYYYYYXXXX.....BBBBAAAA\\n-----END PRIVATE KEY-----\"\n$ export WRU_FORWARD_TO=\"/ =\u003e http://localhost:8080\"\n$ export WRU_USER_1=\"id:user1,name:test user 1,mail:user1@example.com,org:R\u0026D,scope:admin,scope:user,scope:org:rd,twitter:user1,github:user1\"\n$ export WRU_USER_2=\"id:user2,name:test user 2,mail:user2@example.com,org:HR,scope:user,scope:org:hr,twitter:user2,github:user2\"\n$ PORT=8000 HOST=https://localhost:8000 wru\n```\n\n#### WRU for production\n\n![production-mode](doc/dialogs-production-mode.png)\n\nSample configuration:\n\n- Launch at example.com (local port is 8000)\n- No HTTPS by wru (AWS ALB does)\n- A backend server is at http://server.example.com\n- User information is in S3 (and reread it every hour)\n- Session storage is in DynamoDB\n- Twitter/GitHub/OpenID Connect login is available\n\n```bash\n$ export WRU_DEV_MODE=false\n$ export WRU_FORWARD_TO=\"/ =\u003e http://server.example.com\"\n$ export WRU_USER_TABLE=\"s3://my-app-usertable/user-list.csv?region=us-west-1\"\n$ export WRU_USER_TABLE_RELOAD_TERM=1h\n$ export WRU_TWITTER_CONSUMER_KEY=1111111\n$ export WRU_TWITTER_CONSUMER_SECRET=22222222\n$ export WRU_GITHUB_CLIENT_ID=33333333\n$ export WRU_GITHUB_CLIENT_SECRET=44444444\n$ export WRU_OIDC_PROVIDER_URL=http://keycloak.example.com\n$ export WRU_OIDC_CLIENT_ID=55555555\n$ export WRU_OIDC_CLIENT_SECRET=66666666\n$ PORT=8000 HOST=https://example.com wru\n```\n\n### End Points for frontend\n\n- `/.wru/login`: Login page\n- `/.wru/logout`: Logout page (it works just GET access)\n- `/.wru/user`: User page (it supports HTML and JSON)\n- `/.wru/user/sessions`: User session page (it supports HTML and JSON)\n\n### Session Storage\n\nIt supports session storage feature similar to browsers' cookie.\n\n![session storage](doc/dialogs-session-storage.png)\n\nYour web application sends data that will be in the session storage with in `Wru-Set-Session-Data` header field in response like this:\n\n```http\nWru-Set-Session-Data: access-count=10\n```\n\nwru filter this content (browser doesn't retrieve this header field) and store its content in session storage.\nThis content is added to `Wru-Session` header field (you can modify via `WRU_SERVER_SESSION_FIELD` env var) like this:\n\n```go\nWru-Session: {\"login_at\":1212121,\"id\":\"shibu\",\"name\":\"Yoshiki Shibukawa\",\"scopes\":[\"user\",\"admin\"],data:{\"access-count\":\"10\"}}\n```\n\nTo read all content of this field in Go, you can parse it via the following structure:\n\n```go\ntype Session struct {\n\tLoginAt      int64             `json:\"login_at\"`       // nano-seconds\n\tExpireAt     int64             `json:\"expire_at\"`      // nano-seconds\n\tLastAccessAt int64             `json:\"last_access_at\"` // nano-seconds\n\tUserID       string            `json:\"id\"`\n\tDisplayName  string            `json:\"name\"`\n\tEmail        string            `json:\"email\"`\n\tOrganization string            `json:\"org\"`\n\tScopes       []string          `json:\"scopes\"`\n\tData         map[string]string `json:\"data\"`\n}\n\nfunc ParseSession(r *http.Request) (*Session, error) {\n  h := r.Header.Get(\"Wru-Session\")\n  if h != \"\" {\n    var s Session\n    err := json.NewDecoder(strings.NewReader(h)).Decode(\u0026s)\n    if err != nil {\n      return nil, err\n    }\n    return \u0026s, nil\n  }\n  return nil, err\n}\n```\n\n### Configuration\n\n#### Server Configuration\n\n- `PORT`: Port number that wru uses (default is 3000)\n- `HOST`: Host name that wru is avaialble (required). It is used for callback of OAuth/OpenID Connect.\n- `WRU_DEV_MODE`: Change mode (described bellow)\n- `WRU_TLS_CERT` and `WRU_TLS_KEY`: Launch TLS server\n\n### Storage Configuration\n\nWRU stores user information on-memory. You can add user via CSV or env vars.\n\n- `WRU_SESSION_STORAGE`: Session storage. Default is in memory. It supports DynamoDB, Firestore, MongoDB.\n- `WRU_USER_TABLE`: This is local file path/Blob path(AWS S3, GCP Cloud Storage) to read CSV.\n- `WRU_USER_TABLE_RELOAD_TERM`: Reload term.\n- `WRU_USER_%d`: Add user via environment variable (for testing).\n\nIf you add user via env var, you use comma separated tag list:\n\n```bash\nWRU_USER_1=\"id:user1,name:test user 1,mail:user1@example.com,org:R\u0026D,scope:admin,scope:user,scope:org:rd,twitter:user1\"\n```\n\nUser table CSV file should have specific header row.\n\n```csv\nid,name,mail,org,scopes,twitter,github,oidc\nuser1,test user,user1@example.com,R\u0026D,\"admin,user,org:rd\",user1,user1,user1@example.com\n```\n\n### Backend Server Configuration\n\n- `WRU_FORWARD_TO`: Specify you backend server (required)\n- `WRU_SERVER_SESSION_FIELD`: Header field name that WRU adds to backend request (default is \"Wru-Session\")\n\n#### Frontend User Experience Configuration\n\n- `WRU_DEFAULT_LANDING_PAGE`: WRU tries to redirect to referrer page after login. It is used when the path is not available (default is '/').\n- `WRU_LOGIN_TIMEOUT_TERM`: Login session token's expiration term (default is '10m')\n- `WRU_SESSION_IDLE_TIMEOUT_TERM`: Active session token's timeout term (default is '1h')\n- `WRU_SESSION_ABSOLUTE_TIMEOUT_TERM`: Absolute session token's timeout term (default is '720h')\n- `WRU_HTML_TEMPLATE_FOLDER`: Login/User pages' template (default tempalte is embedded ones)\n\n#### ID Provider Configuration\n\nTo enable ID provider connection, set the following env vars.\nThe callback address will be `${HOST}/.wru/callback`. You should register the URL in the setting screen of the ID provider.\n\n##### Twitter\n\n- `WRU_TWITTER_CONSUMER_KEY`\n- `WRU_TWITTER_CONSUMER_SECRET`\n\n##### GitHub\n\n- `WRU_GITHUB_CLIENT_ID`\n- `WRU_GITHUB_CLIENT_SECRET`\n\n##### OpenID Connect\n\n- `WRU_OIDC_PROVIDER_URL`\n- `WRU_OIDC_CLIENT_ID`\n- `WRU_OIDC_CLIENT_SECRET`\n\n#### Extra Option\n\n- `WRU_GEIIP_DATABASE`: GeoIP2 or GeoLite2 file (.mmdb) to detect user location from IP address\n\n## Use as Middleware\n\nwru can work as middleware of HTTP service. Sample is in `cmd/sampleapp`.\n\n`NewAuthorizationMiddleware()` returns required HTTP handler (that includes, login form, callback for OAuth2 and so on) and middleware.\nDon't apply the middleware to the wru's handler (it causes infinity loop).\n\nYou can create `*wru.Config` by using the structure directly or `wru.NewConfigFromEnv()`.\n\n```go\npackage main\n\nimport (\n  \"context\"\n  \"fmt\"\n  \"net/http\"\n  \"os\"\n  \"os/signal\"\n\n  \"github.com/go-chi/chi/v5\"\n  \"github.com/go-chi/chi/v5/middleware\"\n  \"gitlab.com/osaki-lab/wru\"\n\n  // Select backend of session storage (docstore) and identity register (blob)\n  _ \"gocloud.dev/docstore/memdocstore\"\n)\n\nfunc main() {\n\tctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)\n\tdefer stop()\n\n\tr := chi.NewRouter()\n\tc := \u0026wru.Config{\n\t\tPort:    3000,\n\t\tHost:    \"http://localhost:3000\",\n\t\tDevMode: true,\n\t\tUsers: []*wru.User{\n\t\t\t{\n\t\t\t\tDisplayName:  \"Test User 1\",\n\t\t\t\tOrganization: \"Secret\",\n\t\t\t\tUserID:       \"testuser01\",\n\t\t\t\tEmail:        \"testuser01@example.com\",\n\t\t\t},\n\t\t},\n\t}\n\twruHandler, authMiddleware := wru.NewAuthorizationMiddleware(ctx, c, os.Stdout)\n\tr.Use(middleware.Logger)\n\tr.Mount(\"/\", wruHandler)\n\tr.With(authMiddleware).Get(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\t_, session := wru.GetSession(r)\n\t\tw.Write([]byte(\"welcome \" + session.UserID))\n\t})\n    http.ListenAndServe(fmt.Sprintf(\":%d\", c.Port), r)\n}\n```\n\n## License\n\nApache 2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuture-architect%2Ffuture-wru","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuture-architect%2Ffuture-wru","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuture-architect%2Ffuture-wru/lists"}