{"id":37028100,"url":"https://github.com/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter","last_synced_at":"2026-01-14T03:21:09.166Z","repository":{"id":49579854,"uuid":"360305615","full_name":"mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter","owner":"mzlnk","description":"Spring Boot starter for multi-tenant OAuth2 resource server","archived":false,"fork":false,"pushed_at":"2023-03-29T15:19:47.000Z","size":164,"stargazers_count":12,"open_issues_count":4,"forks_count":6,"subscribers_count":1,"default_branch":"develop","last_synced_at":"2025-07-11T06:14:50.346Z","etag":null,"topics":["multi-tenant","oauth2-resource-server","spring-boot","spring-boot-starter"],"latest_commit_sha":null,"homepage":"","language":"Java","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/mzlnk.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-21T21:03:31.000Z","updated_at":"2024-08-13T08:56:08.000Z","dependencies_parsed_at":"2022-08-24T14:39:27.253Z","dependency_job_id":null,"html_url":"https://github.com/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mzlnk","download_url":"https://codeload.github.com/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter/sbom","scorecard":{"id":671793,"data":{"date":"2025-08-11","repo":{"name":"github.com/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter","commit":"48593ea7d986d897db8e253ec750bab7532bd86b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.5,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/21 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact release-1.0.4-beta not signed: https://api.github.com/repos/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter/releases/44539398","Warn: release artifact release-1.0.2-beta not signed: https://api.github.com/repos/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter/releases/42730848","Warn: release artifact release-1.0.1-beta not signed: https://api.github.com/repos/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter/releases/42445376","Warn: release artifact release-1.0.4-beta does not have provenance: https://api.github.com/repos/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter/releases/44539398","Warn: release artifact release-1.0.2-beta does not have provenance: https://api.github.com/repos/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter/releases/42730848","Warn: release artifact release-1.0.1-beta does not have provenance: https://api.github.com/repos/mzlnk/multi-tenant-oauth2-resource-server-spring-boot-starter/releases/42445376"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'develop'","Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 17 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"67 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-h46c-h94j-95f3","Warn: Project is vulnerable to: GHSA-wf8f-6423-gfxg","Warn: Project is vulnerable to: GHSA-3x8x-79m2-3w2w","Warn: Project is vulnerable to: GHSA-57j2-w4cx-62h2","Warn: Project is vulnerable to: GHSA-jjjh-jjxp-wpff","Warn: Project is vulnerable to: GHSA-rgv9-q543-rqg4","Warn: Project is vulnerable to: GHSA-gvpg-vgmx-xg6w","Warn: Project is vulnerable to: GHSA-xwmg-2g98-w7v9","Warn: Project is vulnerable to: GHSA-493p-pfq6-5258","Warn: Project is vulnerable to: GHSA-v528-7hrm-frqp","Warn: Project is vulnerable to: GHSA-rc42-6c7j-7h5r","Warn: Project is vulnerable to: GHSA-xf96-w227-r7c4","Warn: Project is vulnerable to: GHSA-f3jh-qvm4-mg39","Warn: Project is vulnerable to: GHSA-hh32-7344-cg2f","Warn: Project is vulnerable to: GHSA-q3v6-hm2v-pw99","Warn: Project is vulnerable to: GHSA-w9jg-gvgr-354m","Warn: Project is vulnerable to: GHSA-wx54-3278-m5g4","Warn: Project is vulnerable to: GHSA-c4q5-6c82-3qpw","Warn: Project is vulnerable to: GHSA-36p3-wjmg-h94x","Warn: Project is vulnerable to: GHSA-hh26-6xwr-ggv7","Warn: Project is vulnerable to: GHSA-4gc7-5j7h-4qph","Warn: Project is vulnerable to: GHSA-4wp7-92pw-q264","Warn: Project is vulnerable to: GHSA-g5mm-vmx4-3rg7","Warn: Project is vulnerable to: GHSA-6gf2-pvqw-37ph","Warn: Project is vulnerable to: GHSA-rfmp-97jj-h8m6","Warn: Project is vulnerable to: GHSA-558x-2xjg-6232","Warn: Project is vulnerable to: GHSA-564r-hj7v-mcr5","Warn: Project is vulnerable to: GHSA-9cmq-m9j5-mvww","Warn: Project is vulnerable to: GHSA-wxqc-pxw9-g2p8","Warn: Project is vulnerable to: GHSA-2rmj-mq67-h97g","Warn: Project is vulnerable to: GHSA-2wrp-6fg6-hmc5","Warn: Project is vulnerable to: GHSA-4wrc-f8pq-fpqp","Warn: Project is vulnerable to: GHSA-ccgv-vj62-xf9h","Warn: Project is vulnerable to: GHSA-gfwj-fwqj-fp3v","Warn: Project is vulnerable to: GHSA-hgjh-9rj2-g67j","Warn: Project is vulnerable to: GHSA-cx7f-g6mp-7hqm","Warn: Project is vulnerable to: GHSA-g5vr-rgqm-vf78","Warn: Project is vulnerable to: GHSA-w3c8-7r8f-9jp8","Warn: Project is vulnerable to: GHSA-vmq6-5m68-f53m","Warn: Project is vulnerable to: GHSA-668q-qrv7-99fm","Warn: Project is vulnerable to: GHSA-6v67-2wr5-gvf4","Warn: Project is vulnerable to: GHSA-pr98-23f8-jwxv","Warn: Project is vulnerable to: GHSA-27hp-xhwr-wr2m","Warn: Project is vulnerable to: GHSA-5j33-cvvr-w245","Warn: Project is vulnerable to: GHSA-7w75-32cg-r6g2","Warn: Project is vulnerable to: GHSA-83qj-6fr2-vhqg","Warn: Project is vulnerable to: GHSA-fccv-jmmp-qg76","Warn: Project is vulnerable to: GHSA-g8pj-r55q-5c2v","Warn: Project is vulnerable to: GHSA-h2fw-rfh5-95r3","Warn: Project is vulnerable to: GHSA-h3gc-qfqq-6h8f","Warn: Project is vulnerable to: GHSA-hfrx-6qgj-fp6c","Warn: Project is vulnerable to: GHSA-p22x-g9px-3945","Warn: Project is vulnerable to: GHSA-q3mw-pvr8-9ggc","Warn: Project is vulnerable to: GHSA-qppj-fm5r-hxr3","Warn: Project is vulnerable to: GHSA-r6j3-px5g-cq3x","Warn: Project is vulnerable to: GHSA-rq2w-37h9-vg94","Warn: Project is vulnerable to: GHSA-wc4r-xq3c-5cf3","Warn: Project is vulnerable to: GHSA-wm9w-rjj3-j356","Warn: Project is vulnerable to: GHSA-v682-8vv8-vpwr","Warn: Project is vulnerable to: GHSA-v6w3-2prq-h95f","Warn: Project is vulnerable to: GHSA-3mc7-4q67-w48m","Warn: Project is vulnerable to: GHSA-98wm-3w3q-mw94","Warn: Project is vulnerable to: GHSA-9w3m-gqgf-c4p9","Warn: Project is vulnerable to: GHSA-c4r9-r8fh-9vj2","Warn: Project is vulnerable to: GHSA-hhhw-99gj-p3c3","Warn: Project is vulnerable to: GHSA-mjmj-j48q-9wg2","Warn: Project is vulnerable to: GHSA-w37g-rhq8-7m4j"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T20:20:33.871Z","repository_id":49579854,"created_at":"2025-08-21T20:20:33.871Z","updated_at":"2025-08-21T20:20:33.871Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408825,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["multi-tenant","oauth2-resource-server","spring-boot","spring-boot-starter"],"created_at":"2026-01-14T03:21:08.438Z","updated_at":"2026-01-14T03:21:09.160Z","avatar_url":"https://github.com/mzlnk.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Multi-Tenant OAuth2 Resource Server Spring Boot Starter\r\n\r\n[![Licence: MIT](https://img.shields.io/badge/Licence-MIT-blue.svg)](https://shields.io/)\r\n[![Version: BETA-1.0.4](https://img.shields.io/badge/version-1.0.4--beta-yellow.svg)](https://shields.io/)\r\n[![Java : 15](https://img.shields.io/badge/Java-15-orange.svg)](https://jdk.java.net/15/)\r\n[![Open Source](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/)\r\n\r\n\r\n## About\r\n\r\nHave you tried to secure you Spring Boot application with OAuth2 but I haven't found any clear and quick solution for it? If so, this starter is for you!\r\nThe Multi-Tenant OAuth2 Resource Server is a Spring Boot starter created to configure multiple authorization tenants out of the box - just by adding them\r\nin Spring Boot configuration file ;)\r\n\r\n\r\n## Releases\r\n\r\n🚧 The project is currently in BETA. There can be lack of some features or some bugs may still appear. However, we do our best to continuously improve\r\nand develop the starter ;)\r\n\r\n**Latest version:** 1.0.4-beta\r\n\r\n## Getting started!\r\n\r\n### Include Maven dependency:\r\n\r\nIf you want to use the starter in your project - just include proper dependency in your `pom.xml` file (it will automatically download dependencies from Maven Central Repository)\r\n```xml\r\n\u003cdependency\u003e\r\n  \u003cgroupId\u003eio.mzlnk.springframework\u003c/groupId\u003e\r\n  \u003cartifactId\u003emulti-tenant-oauth2-resource-server-spring-boot-starter\u003c/artifactId\u003e\r\n  \u003cversion\u003e1.0.4-beta\u003c/version\u003e\r\n\u003c/dependency\u003e\r\n```\r\n\r\n#\r\n\r\n### Configure Spring Security Configuration:\r\n\r\nTo enable resolving bearer tokens from multiple tenants, you have to attach provided by starter `AuthenticationManagerResolver`. You can do it just by \r\noverriding method from `WebSecurityConfigurerAdapter`. Here is quick example how to do it ;)\r\n```java\r\n@EnableWebSecurity\r\npublic class SecurityConfiguration extends WebSecurityConfigurerAdapter {\r\n\r\n    private final MultitenantAuthenticationManagerResolver resolver;\r\n    \r\n    public SecurityConfiguration(MultitenantAuthenticationManagerResolver resolver) {\r\n        this.resolver = resolver;\r\n    }\r\n\r\n    @Override\r\n    protected void configure(HttpSecurity http) throws Exception {\r\n        http.authorizeRequests()\r\n                .anyRequest().authenticated()\r\n                .and()\r\n                .oauth2ResourceServer()\r\n                .authenticationManagerResolver(resolver);\r\n    }\r\n\r\n}\r\n```\r\n\r\n#\r\n\r\n### Configure how tokens will be resolved\r\n\r\nYou can decide how tokens should be resolved from HTTP request passed to your application. By default, the token is resolved from `Authorization` header, however you can\r\ndetermine that the resource server should read the token from the certain cookie, for instance. To do so, you have to add additional property in `application.yml` configuration file.\r\n\r\nAs for now, there is only one additional way (different from the default one) to resolve token - from the cookie with given name:\r\n```yaml\r\noauth2:\r\n  resource:\r\n    server:\r\n      token-resolver:\r\n        type: COOKIE\r\n        cookie-name: [YOUR_COOKIE_NAME_HERE]\r\n```\r\n\r\n#\r\n\r\n### Add tenants via application configuration\r\n\r\nIf you want to add tenants to your Spring Boot application, you have to edit your `application.yml` file (or corresponding `application.properties` file). Here is \r\nsample YAML config for adding three different tenants:\r\n```yaml\r\noauth2:\r\n  resource:\r\n    server:\r\n      tenants:\r\n        - provider-id: auth-provider-1\r\n          token-type: JWT\r\n          issuer: \"http://localhost:10001/auth/realms/auth-provider-1\"\r\n          jwt-public-key: \"classpath:keys/auth-provider-1.pub\"\r\n\r\n        - provider-id: auth-provider-2\r\n          token-type: JWT\r\n          issuer: \"http://localhost:10002/auth/realms/auth-provider-2\"\r\n          jwt-issuer-uri: \"http://localhost:10002/auth/realms/auth-provider-2\"\r\n\r\n        - provider-id: auth-provider-3\r\n          token-type: OPAQUE\r\n          issuer: \"http://localhost:10003/auth/realms/auth-provider-3\"\r\n          client-id: oauth2-demo\r\n          client-secret: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\r\n          introspect-uri: \"http://localhost:10003/auth/realms/auth-provider-3/protocol/openid-connect/token/introspect\"\r\n          matchers:\r\n            - type: COOKIE\r\n              cookie-name: \"issuer\"\r\n              cookie-value: \"auth-provider-3\"\r\n            - type: HEADER\r\n              header-name: \"Host\"\r\n              header-value: \"mzlnk.io\"\r\n            - type: METHOD\r\n              method: POST\r\n```\r\n\r\nLet's explain what all these properties mean.\r\n\r\nFirst of all, the starter can handle both JWT and opaque tokens - that's why for different tokens we will need to provide different information.\r\nThe table below describes which properties are required both types of tokens.\r\n\r\n| property       | JWT        | opaque     |\r\n| -------------- | ---------- | ---------- |\r\n| provider-id    | *required* | *required* |\r\n| token-type     | *required* | *required* |\r\n| issuer         | *required* | *required* |\r\n| jwt-issuer-uri | *required* |            |\r\n| jwt-public-key | *required* |            |\r\n| client-id      |            | *required* |\r\n| client-secret  |            | *required* |\r\n| introspect-uri |            | *required* |\r\n| matchers       |            | *required* |\r\n\r\n#### property-id:\r\n\r\nThis is id for given authentication tenant. It can by any string but (what's important) it must be unique value among all declared tenants.\r\n\r\n\r\n#### token-type:\r\n\r\nThis property defines what type of token given tenant can handle. The value for this property should be one of:\r\n- `JWT`\r\n- `OPAQUE`\r\n\r\n\r\n#### issuer:\r\n\r\nThis property defines the name of the issuer (here our configured tenant). This is value unique for given provider and determined by the provider itself\r\n(e.g. for Keycloak selfhosted on port 10000: `http://localhost:10002/auth/realms/auth-provider-2`). You have to check what is the value for given provider in their\r\ndocumentation.\r\n\r\n\r\n#### jwt-issuer-uri:\r\n\r\nThis property points to the base Authorization Server URI. This value can also be used to verify the iss claim in provided JWT token.\r\n\r\n\r\n#### jwt-public-key:\r\n\r\nThis property points to JWT public key which is used to verify JWT tokens. It can be file location or key string representation itself.\r\n\r\n\r\n#### client-id:\r\n\r\nThis property defines the client ID (from pair client ID/ client secret) which can be obtained in authorization provider.\r\n\r\n\r\n#### client-secret:\r\n\r\nThis property defines the client secret (from pair client ID/ client secret) which can be obtained in authorization provider.\r\n\r\n\r\n#### introspect-uri:\r\n\r\nThis property points to URI provided by authorization server where the opaque tokens can be verfied.\r\n\r\n\r\n#### matchers:\r\n\r\nBecause of the fact that resource server cannot retrieve issuer directly from opaque token you have to provide additional information (here: *matcher*) which will be used\r\nto determine which authentication tenant should be used to verify incoming opaque token. You can use built-in matchers or create a custom one. For more information\r\ncontinue reading :D\r\n\r\n#\r\n\r\n### Matchers for Authentication Tenant\r\n\r\nAs mentioned before, each opaque token authentication tenant must have at least one declared matcher. It can be cookie, header value, request method,\r\nsome path - there are lots of possibilities! That's why you can create totally custom matcher against incoming request or just use one of most common\r\nmatchers.\r\n\r\n\r\n#### Built-in matchers:\r\n\r\nThere are three built-in matchers provided by the starter:\r\n\r\n\r\n#### Default matcher\r\n\r\nIf you want to use given tenant for all incoming opaque tokens (e.g. you have provided only one authentication tenant), you can use this default built-in matcher which simply matches all incoming request. Here is sample configuration:\r\n```yaml\r\nmatchers:\r\n  - type: DEFAULT\r\n```\r\n\r\n#\r\n\r\n#### Matcher against cookie\r\n\r\nThis matcher can be added via configuration file under `matchers` property. You have to provide cookie name and the value which incoming request have to provide\r\nwith to verify token using given tenant. Here is sample configuration:\r\n```yaml\r\nmatchers:\r\n  - type: COOKIE\r\n    cookie-name: \"issuer\"\r\n    cookie-value: \"auth-provider-1\"\r\n```\r\n\r\nIn above example given tenant will be used to verify token if incoming request will provide cookie with name `issuer` and its value equal to `auth-provider-1`.\r\n\r\n#\r\n\r\n#### Matcher against header:\r\n\r\nThis matcher can be added via configuration file under `matchers` property. You have to provide header name and the value which incoming request have to provide \r\nwith to verify token using given tenant. Here is sample configuration:\r\n```yaml\r\nmatchers:\r\n  - type: HEADER\r\n    header-name: \"Host\"\r\n    header-value: \"mzlnk.io\"\r\n```\r\n\r\nIn above example given tenant will be used to verify token if incoming request will provide `Host` header and its value equal to `mzlnk.io`.\r\n\r\n#\r\n\r\n#### Custom matchers:\r\n\r\nIf built-in matchers are not enough for you, you can easily create a custom one which fits your needs ;) To do it, you have to just create a class which implements\r\n`AuthenticationTenantMatcher` interface and is annotated with `@Matcher`. Here is also quick example:\r\n```java\r\n@Matcher\r\npublic class AuthProvider3Matcher implements AuthenticationTenantMatcher {\r\n\r\n    @Override\r\n    public String getProviderId() {\r\n        return \"auth-provider-3\";\r\n    }\r\n\r\n    @Override\r\n    public boolean matches(HttpServletRequest request) {\r\n        return request.getQueryString().contains(\"iss=auth-provider-3\");\r\n    }\r\n\r\n}\r\n```\r\n\r\nIn example above, we are creating matcher for authentication tenant defined in configuration file with `provider-id` equal to `auth-provider-3`.\r\n\r\n#\r\n\r\n#### Custom matcher factory:\r\n\r\nWhat's more you can create custom matchers which can be used for multiple tenants similarly to the built-in ones. To achieve it, you have to create a class\r\nwhich implements `AuthenticationTenantMatcher.Factory` interface and is annotated with `@MatcherFactory`. Then, add the matcher with required properties in\r\nthe configuration file under `matchers` property for given tenants. Here is quick example how to create custom matcher against request method.\r\n\r\n**AuthenticationMatcherFactory:**\r\n```java\r\n@MatcherFactory\r\npublic class HttpMethodMatcherFactory implements AuthenticationTenantMatcher.Factory {\r\n\r\n    private static final String TYPE = \"METHOD\";\r\n    private static final String METHOD_PROPERTY_KEY = \"method\";\r\n\r\n    @Override\r\n    public String getType() {\r\n        return TYPE;\r\n    }\r\n\r\n    @Override\r\n    public AuthenticationTenantMatcher create(String providerId, \r\n                                              AuthenticationTenantDetails.MatcherDetails matcherDetails) {\r\n        return new HttpMethodMatcher(providerId, matcherDetails.getProperty(METHOD_PROPERTY_KEY));\r\n    }\r\n\r\n    public static class HttpMethodMatcher extends AbstractAuthenticationTenantMatcher {\r\n\r\n        private final String method;\r\n\r\n        public HttpMethodMatcher(String providerId, String method) {\r\n            super(providerId);\r\n            this.method = method;\r\n        }\r\n\r\n        @Override\r\n        public boolean matches(HttpServletRequest request) {\r\n            return request.getMethod().equals(this.method);\r\n        }\r\n    }\r\n\r\n}\r\n```\r\n\r\n**Configuration file:**\r\n```yaml\r\n// ...\r\n- provider-id: auth-provider-1\r\n  // ...\r\n  matchers:\r\n    - type: METHOD\r\n      method: POST\r\n\r\n- provider-id: auth-provider-2\r\n  // ...\r\n  matchers:\r\n    - type: METHOD\r\n      method: GET\r\n```\r\n\r\n#\r\n\r\n### Obtain tenant during handling request\r\n\r\nIf you want to obtain the authentication tenant which the token had been validated against, you can get it via `AuthenticationTenantContextHolder` which is\r\nresponsible for storing current authentication tenant in a context similarly to `SecurityContextHolder`.\r\n\r\n```java\r\nvar tenant = AuthenticationTenantContextHolder.getContext().getAuthenticationTenant();\r\n```\r\n\r\n## Demo\r\n\r\nTo gather all things in one place, there is a simple demo provided in this project [here](https://github.com/mzlnk/spring-boot-multi-tenant-oauth2-resource-server/tree/master/demo).\r\nIt is simple Spring Boot application which uses the starter and all mentioned features so you can check one more time how everything works together :D\r\n\r\n## Want to contribute?\r\n\r\nFeel free to fork this repository and request changes or add features to it. The whole project is built with Maven and Java 15 so these two tools are required\r\nto run the code locally ;)\r\n\r\n## Credits\r\n\r\nThis starter is under MIT licence so feel free to use it for your personal or even commercial use ;)\r\n\r\nCreated by Marcin Zielonka\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmzlnk%2Fmulti-tenant-oauth2-resource-server-spring-boot-starter/lists"}