{"id":17673462,"url":"https://github.com/gwojda/keycloakopenid","last_synced_at":"2025-06-24T01:09:31.457Z","repository":{"id":184989225,"uuid":"672792357","full_name":"Gwojda/keycloakopenid","owner":"Gwojda","description":"keycloakopenid","archived":false,"fork":false,"pushed_at":"2024-01-22T17:15:09.000Z","size":95,"stargazers_count":46,"open_issues_count":7,"forks_count":16,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-12T14:18:55.973Z","etag":null,"topics":["traefik-plugin"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Gwojda.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2023-07-31T07:17:05.000Z","updated_at":"2025-04-05T08:20:34.000Z","dependencies_parsed_at":"2024-01-22T19:08:38.581Z","dependency_job_id":null,"html_url":"https://github.com/Gwojda/keycloakopenid","commit_stats":null,"previous_names":["gwojda/keycloak-openid","gwojda/keycloakopenid"],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/Gwojda/keycloakopenid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gwojda%2Fkeycloakopenid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gwojda%2Fkeycloakopenid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gwojda%2Fkeycloakopenid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gwojda%2Fkeycloakopenid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Gwojda","download_url":"https://codeload.github.com/Gwojda/keycloakopenid/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Gwojda%2Fkeycloakopenid/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261584225,"owners_count":23180674,"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":["traefik-plugin"],"created_at":"2024-10-24T05:23:52.287Z","updated_at":"2025-06-24T01:09:31.427Z","avatar_url":"https://github.com/Gwojda.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Keycloak Authentication Plugin\n\nThis Keycloak authentication plugin is a middleware for Go applications, which manages user authentication using Keycloak, an open-source identity and access management solution.\n\n## Code Explanation\n\n### Structs\n\nThe plugin uses several data structures:\n\n- Config: This struct stores the configuration details of the Keycloak instance, such as the URL, client ID, and client secret.\n  keycloakAuth: This struct is the main component of the plugin, storing the next HTTP handler and the configuration.\n  KeycloakTokenResponse: This struct stores the response from Keycloak when a token is requested.\n- state: This struct stores the URL to which the user should be redirected after successful authentication.\n\n### Main Functions\n\nThe plugin has several main functions:\n\n- CreateConfig(): Initializes and returns a new Config struct.\n- New(): Creates a new Keycloak authentication middleware. It checks the provided configuration and returns an error if the Keycloak URL or client ID is not provided.\n- ServeHTTP(): This is the main function of the middleware. It checks for an \"Authorization\" cookie in the request. If the cookie exists and its value starts with \"Bearer \", it verifies the token. If the token is valid, it allows the request to proceed. If the token is invalid, it redirects the request to Keycloak for authentication. If the cookie does not exist, it checks for an authorization code in the request URL. If the code exists, it exchanges it for a token. If the code does not exist, it redirects the request to Keycloak for authentication.\n- exchangeAuthCode(): Exchanges an authorization code for a token.\n- redirectToKeycloak(): Redirects the request to Keycloak for authentication.\n- verifyToken(): Verifies the validity of a token.\n\n## How it Works\n\nWhen a request is received, the middleware first checks for an \"Authorization\" cookie. If it exists and the token inside is valid, the request is allowed to proceed.\nIf the token is invalid or doesn't exist, the middleware checks for an authorization code in the request URL.\nIf the authorization code exists, the middleware exchanges it for a token, sets this token as a cookie, and redirects the user to their original location.\nIf the authorization code doesn't exist, the middleware redirects the user to Keycloak for authentication.\nThe user is then prompted to enter their credentials on the Keycloak login page. After successful authentication, Keycloak redirects the user back to the application with an authorization code.\nThe middleware then exchanges this code for a token and the process starts over.\nBy using this middleware, applications can easily integrate with Keycloak for user authentication without having to implement the logic themselves.\n\n## Installation\n\nFirst, enable the plugins support in your Traefik configuration file (traefik.yml or traefik.toml):\n\n```yaml\nexperimental:\n  plugins:\n    keycloakopenid:\n      moduleName: \"github.com/Gwojda/keycloakopenid\"\n      version: \"v0.1.35\"\n```\n\nUsage\nAdd the plugin's specific configuration to your Traefik routers:\n\n```yaml\nhttp:\n  middlewares:\n    my-keycloakopenid:\n      plugin:\n        keycloakopenid:\n          KeycloakURL: \"my-keycloak-url.com\" # \u003c- Also supports complete URL, e.g. https://my-keycloak-url.com/auth\n          ClientID: \"\u003cCLIENT_ID\"\n          ClientSecret: \"\u003cCLIENT_SECRET\"\n          KeycloakRealm: \"\u003cREALM\"\n          Scope: \"\u003cScope [space deliminated] (default: 'openid', example: 'openid profile email')\"\n          TokenCookieName: \"\u003cTOKEN_COOKIE_NAME (default: 'AUTH_TOKEN')\"\n          UseAuthHeader: \"\u003ctrue|false (default: false)\"\n          IgnorePathPrefixes: \"/api,/favicon.ico [comma deliminated] (optional)\"\n```\n\nAlternatively, ClientID and ClientSecret can be read from a file to support Docker Secrets and Kubernetes Secrets:\n\n```yaml\nhttp:\n  middlewares:\n    my-keycloakopenid:\n      plugin:\n        keycloakopenid:\n          KeycloakURL: \"https://my-keycloak-url.com/auth\"\n          ClientIDFile: \"/run/secrets/clientId.txt\"\n          ClientSecretFile: \"/run/secrets/clientSecret.txt\"\n          KeycloakRealm: \"\u003cREALM\"\n          Scope: \"\u003cSCOPE [space deliminated] (default: 'openid', example: 'openid profile email')\"\n          TokenCookieName: \"\u003cTOKEN_COOKIE_NAME (default: 'AUTH_TOKEN')\"\n          UseAuthHeader: \"\u003ctrue|false (default: false)\"\n```\n\nLast but not least, each configuration can be read from environment file to support some Kubernetes configurations:\n\n```yaml\nhttp:\n  middlewares:\n    my-keycloakopenid:\n      plugin:\n        keycloakopenid:\n          KeycloakURLEnv: \"MY_KEYCLOAK_URL\"\n          ClientIDEnv: \"MY_KEYCLOAK_CLIENT_ID\"\n          ClientSecretEnv: \"MY_KEYCLOAK_CLIENT_SECRET\"\n          KeycloakRealmEnv: \"MY_KEYCLOAK_REALM\"\n          ScopeEnv: \"SCOPE [space deliminated] (default: 'openid', example: 'openid profile email')\"\n          TokenCookieNameEnv: \"TOKEN_COOKIE_NAME (default: 'AUTH_TOKEN')\"\n          UseAuthHeaderEnv: \"USE_AUTH_HEADER (default: false)\"\n```\n\nThis plugin also sets a header with a claim from Keycloak, as it has become reasonably common. Claim name and header name can be modified.  \nThe default claim is \u003ccode\u003epreferred_username\u003c/code\u003e, the default header name is \u003ccode\u003eX-Forwarded-User\u003c/code\u003e :\n\n```yaml\nhttp:\n  middlewares:\n    my-keycloakopenid:\n      plugin:\n        keycloakopenid:\n          KeycloakURL: \"my-keycloak-url.com\" # \u003c- Also supports complete URL, e.g. https://my-keycloak-url.com/auth\n          ClientID: \"\u003cCLIENT_ID\"\n          ClientSecret: \"\u003cCLIENT_SECRET\"\n          KeycloakRealm: \"\u003cREALM\"\n          Scope: \"\u003cSCOPE [space deliminated] (default: 'openid', example: 'openid profile email')\"\n          TokenCookieName: \"TOKEN_COOKIE_NAME (default: \"AUTH_TOKEN)\"\n          UseAuthHeader: \"true|false (default: false)\"\n          UserClaimName: \"my-uncommon-claim\"\n          UserHeaderName: \"X-Custom-Header\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgwojda%2Fkeycloakopenid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgwojda%2Fkeycloakopenid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgwojda%2Fkeycloakopenid/lists"}