{"id":25524757,"url":"https://github.com/radekg/ory-reference-compose","last_synced_at":"2026-01-01T03:30:17.112Z","repository":{"id":48463291,"uuid":"356677626","full_name":"radekg/ory-reference-compose","owner":"radekg","description":"Reference ORY Docker Compose setup","archived":true,"fork":false,"pushed_at":"2021-07-24T19:11:29.000Z","size":765,"stargazers_count":58,"open_issues_count":0,"forks_count":16,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-04-08T16:32:22.697Z","etag":null,"topics":["docker","docker-compose","dockerfile","iam","ory","sso"],"latest_commit_sha":null,"homepage":"https://gruchalski.com/posts/2021-04-10-ory-reference-docker-compose-and-thoughts-on-the-platform/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/radekg.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-04-10T19:39:53.000Z","updated_at":"2024-04-04T03:07:41.000Z","dependencies_parsed_at":"2022-08-24T06:10:21.781Z","dependency_job_id":null,"html_url":"https://github.com/radekg/ory-reference-compose","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekg%2Fory-reference-compose","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekg%2Fory-reference-compose/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekg%2Fory-reference-compose/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/radekg%2Fory-reference-compose/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/radekg","download_url":"https://codeload.github.com/radekg/ory-reference-compose/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239727073,"owners_count":19687098,"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":["docker","docker-compose","dockerfile","iam","ory","sso"],"created_at":"2025-02-19T20:05:34.678Z","updated_at":"2026-01-01T03:30:17.034Z","avatar_url":"https://github.com/radekg.png","language":null,"funding_links":[],"categories":["Archived, Outdated, and WIP"],"sub_categories":["Ory Fosite"],"readme":"## Build base components\n\nClone and build individual components:\n\n### Hydra\n\n```sh\nmkdir -p $GOPATH/src/github.com/ory/hydra\ncd $GOPATH/src/github.com/ory/hydra\ngit clone https://github.com/ory/hydra.git .\ngit checkout v1.10.3\ndocker build -t ory-hydra:v1.10.3 -f .docker/Dockerfile-build .\n```\n\n### Keto\n\n```sh\nmkdir -p $GOPATH/src/github.com/ory/keto\ncd $GOPATH/src/github.com/ory/keto\ngit clone https://github.com/ory/keto.git .\ngit checkout v0.6.0-alpha.3\ndocker build -t ory-keto:v0.6.0-alpha.3 -f .docker/Dockerfile-build .\n```\n\n### Kratos\n\n```sh\nmkdir -p $GOPATH/src/github.com/ory/kratos\ncd $GOPATH/src/github.com/ory/kratos\ngit clone https://github.com/ory/kratos.git .\ngit checkout v0.7.1-alpha.1\ndocker build -t ory-kratos:v0.7.1-alpha.1 -f .docker/Dockerfile-build .\n```\n\n### Oathkeeper\n\nRight now, Oathkeeper is the only component not providing Docker based build:\n\n```sh\nmkdir -p $GOPATH/src/github.com/ory/oathkeeper\ncd $GOPATH/src/github.com/ory/oathkeeper\ngit clone https://github.com/ory/oathkeeper.git .\ngit checkout v0.38.14-beta.1\nmake .bin/packr2\n./.bin/packr2\nCGO_ENABLED=0 GO111MODULE=on GOOS=linux GOARCH=amd64 go build\ndocker build -t ory-oathkeeper:v0.38.14-beta.1 .\nrm oathkeeper\n./.bin/packr2 clean\n```\n\n## Build additional components required by the Compose setup\n\n### Kratos self service UI\n\nThis is an example browser facing application implementing login, registration, verification and link recovery flows:\n\n```sh\nmkdir -p $GOPATH/src/github.com/ory/kratos-selfservice-ui-node\ncd $GOPATH/src/github.com/ory/kratos-selfservice-ui-node\ngit clone https://github.com/ory/kratos-selfservice-ui-node.git .\ngit checkout v0.7.1-alpha.1\ndocker build -t ory-kratos-selfservice-ui-node:v0.7.1-alpha.1 .\n```\n\n### Mailslurper\n\nKratos always sends emails and mailslurper is a thin SMTP server used by the Compose:\n\n```\nmkdir -p $GOPATH/src/github.com/ory/mailslurper\ncd $GOPATH/src/github.com/ory/mailslurper\ngit clone https://github.com/ory/mailslurper.git .\ngit checkout master\ndocker build -t ory-mailslurper:master -f Dockerfile-smtps .\n```\n\n## Run\n\n```sh\ncd compose/\ndocker run --rm -ti ory-oathkeeper:v0.38.14-beta.1 credentials generate --alg RS256 \u003e configs/oathkeeper/jwks.json\ndocker-compose -f compose.yml up\n```\n\n## Test individual components\n\n### Hydra\n\nCreate an OAuth 2.0 Client:\n\n```sh\ndocker-compose -f compose.yml exec hydra \\\n    hydra clients create \\\n    --endpoint http://127.0.0.1:4445/ \\\n    --id my-client \\\n    --secret secret \\\n    -g client_credentials\n```\n\nList clients:\n\n```sh\ndocker-compose -f compose.yml exec hydra \\\n    hydra clients list \\\n    --endpoint http://127.0.0.1:4445/\n```\n\nPerform credentials grant:\n\n```sh\ndocker-compose -f compose.yml exec hydra \\\n    hydra token client \\\n    --endpoint http://127.0.0.1:4444/ \\\n    --client-id my-client \\\n    --client-secret secret \\\n    --scope openid,offline\n```\n\nCopy the output access token and introspect:\n\n```sh\ndocker-compose -f compose.yml exec hydra \\\n    hydra token introspect \\\n    --endpoint http://127.0.0.1:4445/ ...access token goes here...\n```\n\n### Keto\n\nThe namespaces are defined in the `compose/configs/keto/keto.yml` file.\n\nCreate a relation tuple:\n\n```sh\ncurl -XPUT --data '{\n  \"namespace\": \"default-namespace\",\n  \"object\": \"blog_posts:my-first-blog-post\",\n  \"relation\": \"delete\",\n  \"subject\": \"alice\"\n}' http://localhost:4467/relation-tuples\n```\n\nCheck if the tuple has been created:\n\n```sh\ncurl http://localhost:4466/relation-tuples?namespace=default-namespace\n```\n\nCheck if user Alice is allowed to delete the blog post:\n\n```sh\ncurl -XPOST --data '{\n  \"namespace\": \"default-namespace\",\n  \"object\": \"blog_posts:my-first-blog-post\",\n  \"relation\": \"delete\",\n  \"subject\": \"alice\"\n}' http://localhost:4466/check\n```\n\n### Kratos\n\nVerify that Kratos is up:\n\n```sh\ncurl --silent http://localhost:4433/health/alive | jq '.'\n```\n\nThe result should be:\n\n```json\n{\n  \"status\": \"ok\"\n}\n```\n\nNow, open `http://127.0.0.1:4455/dashboard` in the browser. You should see the following self service app UI:\n\n![Self service Kratos UI](docs/aaa-setup-kratos-self-service-ui.png)\n\nRegister an account and sign in.\n\n![Self service Kratos UI signed in user](docs/aaa-setup-kratos-signed-in.png)\n\n### Oathkeeper\n\nThe rules are defined in `compose/configs/oathkeeper/rules.json` file. The `allow-anonymous-with-header-mutator` rule allows an unauthenticated access to the `http://127.0.0.1:4455/anything/header` URL. Here we validate that:\n\n```sh\ncurl -X GET http://127.0.0.1:4455/anything/header\n```\n\nGives:\n\n```json\n{\n  \"args\": {},\n  \"data\": \"\",\n  \"files\": {},\n  \"form\": {},\n  \"headers\": {\n    \"Accept\": \"*/*\",\n    \"Accept-Encoding\": \"gzip\",\n    \"Host\": \"httpbin.org\",\n    \"User-Agent\": \"curl/7.54.0\",\n    \"X-Amzn-Trace-Id\": \"Root=1-5f91f003-273d759c25c50cdd24be33c6\",\n    \"X-User\": \"guest\"\n  },\n  \"json\": null,\n  \"method\": \"GET\",\n  \"origin\": \"172.22.0.1, 92.209.32.233\",\n  \"url\": \"https://httpbin.org/anything/header/anything/header\"\n}\n```\n\nThe `deny-anonymous` rule disallows anonymous access to the `http://127.0.0.1:4455/anything/deny` URL.\n\n```sh\ncurl --silent -H \"Accept: application/json\" -X GET http://127.0.0.1:4455/anything/deny | jq '.'\n```\n\nReturns:\n\n```json\n{\n  \"error\": {\n    \"code\": 403,\n    \"status\": \"Forbidden\",\n    \"message\": \"Access credentials are not sufficient to access this resource\"\n  }\n}\n```\n\n## Scenario\n\nThis scenario combines `hydra`, `keto` and `oathkeeper` together to build an end to end example where `oathkeeper` provides a rule protecting an endpoint using OAuth2 token and a `keto` permission. This is a first iteration and requires quite some switching between the terminal and a browser.\n\n### Create an OpenID Client\n\n```sh\ndocker-compose -f compose.yml exec hydra \\\n    hydra clients create \\\n    --endpoint http://127.0.0.1:4445 \\\n    --id scenario-client \\\n    --secret secret \\\n    --grant-types authorization_code,refresh_token \\\n    --response-types code,id_token \\\n    --scope openid,offline \\\n    --callbacks http://127.0.0.1:5555/callback\n```\n\n#### List Clients\n\n```sh\ndocker-compose -f compose.yml exec hydra \\\n    hydra clients list \\\n    --endpoint http://127.0.0.1:4445\n```\n\n### Request a user token\n\n```sh\ndocker-compose -f compose.yml exec hydra \\\n    hydra token user \\\n    --client-id scenario-client \\\n    --client-secret secret \\\n    --endpoint http://127.0.0.1:4444/ \\\n    --port 5555 \\\n    --scope openid,offline\n```\n\nThis will require navigating to `http://127.0.0.1:5555` in the browser.\n\n![Exemplary OAuth 2.0 Consumer](docs/001-exemplary-oauth-2-consumer.png)\n\nClick `Authorize application` link. The result is an empty page with a URL containing a `login_challenge` parameter.\n\n![Authorize application](docs/002-login-challenge.png)\n\nCopy the `login_challenge` value from the URL and proceed:\n\n```sh\nexport login_challenge=...\n```\n\n```sh\ncurl --silent -XPUT http://localhost:4445/oauth2/auth/requests/login/accept?login_challenge=${login_challenge} -d '{\n  \"acr\": \"lol\",\n  \"remember\": false,\n  \"remember_for\": 0,\n  \"subject\": \"scenario\"\n}' | jq '.'\n```\n\nThe result is a JSON value similar to:\n\n```json\n{\n  \"redirect_to\": \"http://127.0.0.1:4444/oauth2/auth?audience=\u0026client_id=scenario-client\u0026login_verifier=fce3f73081244383a41b1776f0e8b259\u0026max_age=0\u0026nonce=ukpogmszferrybsixvvnmdyk\u0026prompt=\u0026redirect_uri=http%3A%2F%2F127.0.0.1%3A5555%2Fcallback\u0026response_type=code\u0026scope=openid+offline\u0026state=zxzwdotymvehgmolwfujojsd\"\n}\n```\n\nCopy the value of `redirect_to` and navigate to that URL in the browser. You will be redirected to the `consent_challenge`.\n\n![Consent challenge](docs/003-consent-challenge.png)\n\nCopy the value of the `consent_challenge` and proceed:\n\n```sh\nexport consent_challenge=...\n```\n\n```sh\ncurl --silent -XPUT http://localhost:4445/oauth2/auth/requests/consent/accept?consent_challenge=${consent_challenge} -d '{\n  \"grant_access_token_audience\": [\n    \"scenario-client\"\n  ],\n  \"grant_scope\": [\n    \"openid\", \"offline\"\n  ],\n  \"handled_at\": \"2020-10-23T20:49:00Z\",\n  \"remember\": false,\n  \"remember_for\": 0,\n  \"session\": {\n    \"id_token\": {\n      \"first_name\": \"Ha\",\n      \"last_name\": \"Hahah\"\n    }\n  }\n}' | jq '.'\n```\n\nThe `session.id_token` property is how the additional claims can be passed to the ID token via user info. This behaviour is documented here: https://www.ory.sh/hydra/docs/concepts/openid-connect-oidc#userinfo. This is the basic primitive for integrating Kratos and Hydra.\n\nThe result will be another JSON like this:\n\n```json\n{\n  \"redirect_to\": \"http://127.0.0.1:4444/oauth2/auth?audience=\u0026client_id=scenario-client\u0026consent_verifier=154fc48c8aec46c79c8d0a27c1b7aab4\u0026max_age=0\u0026nonce=ukpogmszferrybsixvvnmdyk\u0026prompt=\u0026redirect_uri=http%3A%2F%2F127.0.0.1%3A5555%2Fcallback\u0026response_type=code\u0026scope=openid+offline\u0026state=zxzwdotymvehgmolwfujojsd\"\n}\n```\n\nAgain, copy the URL and navigate to it in the browser. You will now see the page with access token, refresh token and ID token.\n\n![Tokens](docs/004-tokens.png)\n\nCopy the value of the access token and run the final steps.\n\n### Create the keto policy\n\n```sh\ncurl -XPUT --data '{\n  \"namespace\": \"default-namespace\",\n  \"object\": \"token:and:keto\",\n  \"relation\": \"get\",\n  \"subject\": \"scenario\"\n}' http://localhost:4467/relation-tuples\n```\n\nAnd validate the token - make sure you put the token in the command instead of `...access_token...`:\n\n```sh\ncurl -H \"Authorization: Bearer ...access_token...\" http://127.0.0.1:4455/anything/token-and-keto\n```\n\nThe result is similar to:\n\n```json\n{\n  \"args\": {},\n  \"data\": \"\",\n  \"files\": {},\n  \"form\": {},\n  \"headers\": {\n    \"Accept\": \"*/*\",\n    \"Accept-Encoding\": \"gzip\",\n    \"Authorization\": \"Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzoxZjViOWYwMS0xZTk4LTQ0M2QtOGVjYi01M2RlYjI2NWYxZWIiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOlsic2NlbmFyaW8tY2xpZW50Il0sImNsaWVudF9pZCI6InNjZW5hcmlvLWNsaWVudCIsImV4cCI6MTYwMzQ5NTgyNSwiZXh0Ijp7fSwiaWF0IjoxNjAzNDkyMjI0LCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjQ0NDQvIiwianRpIjoiMWMyMjYxMWQtOWRhNS00NmIwLWJkN2MtYzM3ZDk5ODhjOWIxIiwibmJmIjoxNjAzNDkyMjI0LCJzY3AiOlsib3BlbmlkIiwib2ZmbGluZSJdLCJzdWIiOiJzY2VuYXJpbyJ9.aaadR9WL-kAT7TFM9ra-loA6MOYJSgb_RqwgxDjKLMmQ3Cj16_jC3Pi7zKEgfwCS6npb_6mACFRkwCE9Ih5cApuiKjbQXd2pZNrGacywqYmHFD1H_lDT6z2wxEnVJFYDtaCPcufn7YsN0HbRyCNGAXX_eAJoMbp0pa0J8q3penukAEviphRztIzAV6gMrN45G8YM9DWjLsxw44luW2rbRH6F78AdugZkL78JYqIeSwn5Tu93XJ34buPzsdjaMOiyEV9xABgtLTfV3joOneT-yJYTAPj8CCGpxB3LCMTSvBzjiIN7eqcPcw84Kg6zE-cqWfnc3xyQojiFvypOdB-sJKI79n5D3mUdfAmx1fW_-6BoBDw2_nVaFHMS_yLyr9q5vK2FrOj7Cw6VeeoLbZYVREPM6QAdR7Jrleo-mheDS4XixThmmmRqTcduatYRXedTADoh57ICzSVOEJOZ0HP5o4OjUeTrXrm9yn7voxNbR6y-wrLdZZJ7SsQ498NrE72qKzZp-O8UmPWuKOeXt4MBPIVlmYmrjjQ0WseS_4yg3u6rvk80mb5EVaS8cN8dhuzIkHtv0OyOqccqWNVW57VdMza7reN2b0pd-JOmJayZHuO6tcEYsscjtxCZfIteoDiPEXXvKdAGG_8vdo0f53B7wRcEZTDKqqYTitY16G9qh8A\",\n    \"Host\": \"httpbin.org\",\n    \"User-Agent\": \"curl/7.54.0\",\n    \"X-Amzn-Trace-Id\": \"Root=1-5f935a2e-044927e62c7ddc6b1038475f\"\n  },\n  \"json\": null,\n  \"method\": \"GET\",\n  \"origin\": \"172.22.0.1, 92.209.32.233\",\n  \"url\": \"https://httpbin.org/anything/token-and-keto/anything/token-and-keto\"\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradekg%2Fory-reference-compose","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fradekg%2Fory-reference-compose","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fradekg%2Fory-reference-compose/lists"}