{"id":16358183,"url":"https://github.com/newam/oidc_pages","last_synced_at":"2025-09-24T05:32:08.034Z","repository":{"id":247238467,"uuid":"825341308","full_name":"newAM/oidc_pages","owner":"newAM","description":"Serve static HTML with OIDC for authorization and authentication","archived":false,"fork":false,"pushed_at":"2025-01-09T01:59:22.000Z","size":498,"stargazers_count":0,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-09T02:38:53.111Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/newAM.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-07T14:12:20.000Z","updated_at":"2025-01-09T01:59:34.000Z","dependencies_parsed_at":"2024-09-17T06:49:17.000Z","dependency_job_id":"2c02d6d0-10f4-4a33-b545-8a67dea27b4f","html_url":"https://github.com/newAM/oidc_pages","commit_stats":{"total_commits":63,"total_committers":2,"mean_commits":31.5,"dds":0.04761904761904767,"last_synced_commit":"b9136794c5c4c819b86d25c23277efd9b921136b"},"previous_names":["newam/oidc_pages"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Foidc_pages","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Foidc_pages/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Foidc_pages/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/newAM%2Foidc_pages/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/newAM","download_url":"https://codeload.github.com/newAM/oidc_pages/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234045462,"owners_count":18770949,"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":"2024-10-11T02:05:00.053Z","updated_at":"2025-09-24T05:32:08.021Z","avatar_url":"https://github.com/newAM.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OIDC Pages\n\nOIDC Pages is a static HTML document server that integrates OpenID Connect (OIDC) for authentication and per-document authorization (permissions).\nOIDC Pages is designed to work seamlessly with documentation tools such as Sphinx, Doxygen, and mdbook, and can be used with any static HTML content.\n\n## Screenshots\n\n![OIDC Pages index](/screenshots/index.png?raw=true \"OIDC Pages index\")\n\n## Features\n\n- Works with keycloak or kanidm\n- Respects system dark / light settings\n- NixOS module provided\n- Supports dynamically uploaded documents\n- Secure by default\n\n### Limitations\n\n- Sessions are stored in-memory and erased on restart\n- Not intended for serving untrusted content\n\n### Adapting to other OIDC providers\n\n1. **Access Token Type**\n   - The OIDC specification doesn't define a type for the access token.\n   - Your OIDC provider must use a JSON web token which is the de-facto standard.\n2. **Roles Path Configuration**\n   - The OIDC specification doesn't provide a standard way to read roles.\n   - To configure the path to the roles in the token, use the `roles_path` setting in your configuration file.\n   - Determining the appropriate value for `roles_path` typically involves inspecting the return data from your OIDC provider. This can be done by examining the responses from a working application.\n\n### Planned features\n\nThese features may or may not happen.\n\n- Public pages\n- Persistent user sessions\n- Refresh tokens\n- API for uploading pages over https\n- [Pretty error pages](https://docs.rs/tower-http/0.6.2/tower_http/services/struct.ServeDir.html#method.not_found_service)\n- Serving pages from subdomains instead of paths\n- Pictorial preview of pages\n\n## Security\n\nPlease report vulnerabilities to my git committer email.\n\n## Technology\n\n- Language: [rust](https://www.rust-lang.org)\n- Asynchronous runtime: [tokio](https://tokio.rs)\n- Web framework: [axum](https://github.com/tokio-rs/axum)\n- Session management: [tower-sessions](https://github.com/maxcountryman/tower-sessions)\n- Templating engine: [askama](https://github.com/djc/askama)\n- OpenID Connect library: [openidconnect-rs](https://github.com/ramosbugs/openidconnect-rs)\n- Favicon provided by [Flowbite](https://flowbite.com/icons)\n\n## Configuration\n\nThis is designed to work with [NixOS], but should work on any Linux OS with\nsystemd.\n\nYou need to bring a reverse proxy for TLS, I suggest [nginx].\n\n### Keycloak configuration\n\n- Create and enable an OpenID Connect client in your realm\n  - Root URL: `https://pages.company.com`\n  - Home URL: `https://pages.company.com`\n  - Valid redirect URIs: `https://pages.company.com/callback`\n  - Client authentication: `On`\n  - Authorization: `Off`\n  - Authentication flow: `Standard flow` (all others disabled)\n- Create roles for the newly created client\n  - The `admin` role can view all pages\n  - All other roles grant permissions to pages in a directory matching the role name\n- Create a dedicated audience mapper for the newly created client\n  - Navigate to **Clients** -\u003e `\u003cclient_id\u003e` -\u003e **Client scopes**\n    -\u003e `\u003cclient_id\u003e-dedicated` -\u003e **Configure a new mapper** -\u003e **Audience**\n  - Name: `aud-mapper-\u003cclient_id\u003e`\n  - Included Client Audience: `\u003cclient_id\u003e`\n  - Add to ID token: `On`\n  - Add to access token: `On`\n  - Add to lightweight access token: `Off`\n  - Add to token introspection: `On`\n\n### Kanidm configuration\n\nCreate the OAuth2 client:\n\n```bash\nkanidm system oauth2 create pages \"pages.domain.name\" https://pages.domain.name\nkanidm system oauth2 update-scope-map pages oidc_pages_users email openid profile groups\nkanidm system oauth2 get pages\nkanidm system oauth2 show-basic-secret pages\n\u003cSECRET\u003e\n```\n\nCreate permission groups:\n\n```bash\nkanidm group create 'oidc_pages_users'\nkanidm group create 'oidc_pages_pagename'\n```\n\nSetup the claim map:\n\n```bash\nkanidm system oauth2 update-claim-map-join 'pages' 'pages_roles' array\nkanidm system oauth2 update-claim-map 'pages' 'pages_roles' 'oidc_pages_pagename' 'pagename'\n```\n\nAdd users to the groups:\n\n```bash\nkanidm person update myusername --legalname \"Personal Name\" --mail \"user@example.com\"\nkanidm group add-members 'oidc_pages_users' 'myusername'\nkanidm group add-members 'oidc_pages_pagename' 'myusername'\n```\n\n### NixOS configuration\n\nReference `nixos/module.nix` for a complete list of options,\nbelow is an example of my configuration.\n\n```nix\n{\n  oidc_pages,\n  config,\n  ...\n}: let\n  pagesDomain = \"pages.company.com\";\nin {\n  # import the module, this adds the \"services.oidc_pages\" options\n  imports = [oidc_pages.nixosModules.default];\n\n  # add the overlay, this puts \"oidc_pages\" into \"pkgs\"\n  nixpkgs.overlays = [oidc_pages.overlays.default];\n\n  # use nix-sops to manage secrets declaratively\n  # https://github.com/Mic92/sops-nix\n  sops.secrets.oidc_pages.mode = \"0400\";\n\n  # reference module for descriptions of configuration\n  services.oidc_pages = {\n    enable = true;\n    # contains\n    # OIDC_PAGES_CLIENT_SECRET=client_secret_goes_here\n    environmentFiles = [config.sops.secrets.oidc_pages.path];\n    # give nginx access to oidc_pages.socket\n    socketUser = config.services.nginx.user;\n    settings = {\n      public_url = \"https://${pagesDomain}\";\n      client_id = \"pages\";\n      pages_path = \"/var/www/pages\";\n      log_level = \"info\";\n      # provider specific:\n      # - keycloak: \"https://sso.company.com/realms/company\"\n      # - kanidm: \"https://sso.company.com/oauth2/openid/${client_id}\"\n      issuer_url = \"\";\n      # provider specific:\n      # - keycloak: [\"roles\"]\n      # - kanidm: []\n      additional_scopes = [];\n      # provider specific:\n      # - keycloak: [\"resource_access\" client_id \"roles\"]\n      # - kanidm: [\"pages_roles\"]\n      roles_path = [];\n    };\n  };\n\n  # use NGINX as a reverse proxy to provide a TLS (https) interface\n  networking.firewall.allowedTCPPorts = [443];\n  services.nginx = {\n    enable = true;\n    virtualHosts.\"${pagesDomain}\" = {\n      onlySSL = true;\n      locations.\"/\".proxyPass = \"http://unix:${config.services.oidc_pages.bindPath}\";\n    };\n  };\n}\n```\n\n[NixOS]: https://nixos.org\n[nginx]: https://nginx.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnewam%2Foidc_pages","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnewam%2Foidc_pages","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnewam%2Foidc_pages/lists"}