├── .github ├── dependabot.yml └── workflows │ ├── add-to-projects.yml │ ├── test.yml │ └── triggerConversion.yml ├── .gitignore ├── .travis.yml.disabled ├── CONTRIBUTING.md ├── LICENSE ├── README.adoc ├── assets └── JWT_Diagram.png ├── finish ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── frontend │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── io │ │ │ └── openliberty │ │ │ └── guides │ │ │ └── frontend │ │ │ ├── ApplicationBean.java │ │ │ ├── LoginBean.java │ │ │ ├── client │ │ │ ├── .gitkeep │ │ │ └── SystemClient.java │ │ │ ├── filters │ │ │ └── NoCacheFilter.java │ │ │ ├── models │ │ │ └── SystemModel.java │ │ │ └── util │ │ │ └── SessionUtils.java │ │ ├── liberty │ │ └── config │ │ │ ├── resources │ │ │ └── security │ │ │ │ └── key.p12 │ │ │ └── server.xml │ │ └── webapp │ │ ├── WEB-INF │ │ └── web.xml │ │ ├── application.xhtml │ │ ├── error.xhtml │ │ ├── favicon.ico │ │ ├── index.xhtml │ │ └── login.xhtml ├── mvnw ├── mvnw.cmd ├── pom.xml └── system │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── openliberty │ │ │ └── guides │ │ │ └── system │ │ │ ├── SystemApplication.java │ │ │ └── SystemResource.java │ ├── liberty │ │ └── config │ │ │ ├── resources │ │ │ └── security │ │ │ │ └── key.p12 │ │ │ └── server.xml │ ├── resources │ │ └── META-INF │ │ │ └── microprofile-config.properties │ └── webapp │ │ ├── WEB-INF │ │ └── web.xml │ │ ├── favicon.ico │ │ └── index.html │ └── test │ └── java │ └── it │ └── io │ └── openliberty │ └── guides │ └── system │ ├── SystemEndpointIT.java │ └── util │ └── JwtBuilder.java ├── scripts ├── dailyBuild.sh └── testApp.sh └── start ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── frontend ├── pom.xml └── src │ └── main │ ├── java │ └── io │ │ └── openliberty │ │ └── guides │ │ └── frontend │ │ ├── LoginBean.java │ │ ├── client │ │ └── .gitkeep │ │ ├── filters │ │ └── NoCacheFilter.java │ │ ├── models │ │ └── SystemModel.java │ │ └── util │ │ └── SessionUtils.java │ ├── liberty │ └── config │ │ ├── resources │ │ └── security │ │ │ └── key.p12 │ │ └── server.xml │ └── webapp │ ├── WEB-INF │ └── web.xml │ ├── application.xhtml │ ├── error.xhtml │ ├── favicon.ico │ ├── index.xhtml │ └── login.xhtml ├── mvnw ├── mvnw.cmd ├── pom.xml └── system ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── openliberty │ │ └── guides │ │ └── system │ │ └── SystemApplication.java ├── liberty │ └── config │ │ ├── resources │ │ └── security │ │ │ └── key.p12 │ │ └── server.xml ├── resources │ └── META-INF │ │ └── .gitkeep └── webapp │ ├── WEB-INF │ └── web.xml │ ├── favicon.ico │ └── index.html └── test └── java └── it └── io └── openliberty └── guides └── system └── util └── JwtBuilder.java /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/finish" 5 | schedule: 6 | interval: monthly 7 | open-pull-requests-limit: 50 8 | - package-ecosystem: maven 9 | directory: "/start" 10 | schedule: 11 | interval: monthly 12 | open-pull-requests-limit: 50 13 | -------------------------------------------------------------------------------- /.github/workflows/add-to-projects.yml: -------------------------------------------------------------------------------- 1 | name: Add issues to Liberty guides backlog project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | - transferred 8 | 9 | jobs: 10 | add-to-project: 11 | name: Add issue to backlog 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/add-to-project@v0.4.0 15 | with: 16 | project-url: https://github.com/orgs/OpenLiberty/projects/11 17 | github-token: ${{ secrets.ADMIN_BACKLOG }} 18 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test application 2 | 3 | on: 4 | pull_request: 5 | branches: [ prod, staging ] 6 | 7 | jobs: 8 | check-files: 9 | if: ${{ github.event_name == 'pull_request' }} 10 | runs-on: ubuntu-latest 11 | outputs: 12 | canSkip: ${{ steps.Checker.outputs.canSkip }} 13 | steps: 14 | - name: Get files 15 | uses: actions/checkout@v4 16 | - name: Get tools 17 | uses: actions/checkout@v4 18 | with: 19 | path: tools/ 20 | repository: openliberty/guides-common 21 | - id: Checker 22 | shell: bash 23 | run: bash ./tools/pr-checker/checker.sh ${{ github.repository }} ${{ github.event.pull_request.number }} | tee checker.log 24 | - id: Lint-Code-Base 25 | if: "! github.event.pull_request.head.repo.fork" 26 | uses: github/super-linter@latest 27 | env: 28 | VALIDATE_ALL_CODEBASE: false 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | LINTER_RULES_PATH: ./tools/pr-checker/linters/ 31 | FILTER_REGEX_EXCLUDE: mvnw* 32 | DEFAULT_BRANCH: prod 33 | - name: Summary 34 | if: "! github.event.pull_request.head.repo.fork" 35 | run: | 36 | < ./checker.log tail -n +2; echo "====== Super Linter ======" 37 | < ./super-linter.log sed -n '/.*The script has completed.*/,$p' | tail -n +4 | sed 's/.*\(\[[A-Z]\+\]\)/\1/' 38 | echo "====== Examine logs in Checker and Super-Linter steps for more details ======" 39 | if [ '${{ steps.Checker.outcome }}' != 'success' ] || [ '${{ steps.Lint-Code-Base.outcome }}' != 'success' ]; then exit 1; fi 40 | test-app: 41 | runs-on: ubuntu-latest 42 | needs: [check-files] 43 | if: "!contains(needs.check-files.outputs.canSkip, 'true')" 44 | defaults: 45 | run: 46 | working-directory: finish 47 | steps: 48 | - uses: actions/checkout@v4 49 | - name: Set up JDK 11 50 | uses: actions/setup-java@v4 51 | with: 52 | distribution: 'semeru' 53 | java-version: 11 54 | - run: unset _JAVA_OPTIONS 55 | - name: Run tests 56 | run: sudo -E ../scripts/testApp.sh 57 | - name: Post tests 58 | if: always() 59 | run: | 60 | logsPath=$(sudo find . -name "console.log"); 61 | sudo cat "$logsPath" | sudo grep Launching 62 | - name: Archive server logs if failed 63 | if: failure() 64 | uses: actions/upload-artifact@v4 65 | with: 66 | name: server-logs 67 | path: finish/system/target/liberty/wlp/usr/servers/defaultServer/logs/ 68 | -------------------------------------------------------------------------------- /.github/workflows/triggerConversion.yml: -------------------------------------------------------------------------------- 1 | name: Rebuild cloud-hosted guide 2 | 3 | # Controls when the action will run. Triggers the workflow on push 4 | # events but only for the master branch 5 | on: 6 | push: 7 | branches: 8 | - 'prod' 9 | - 'staging' 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "post" 14 | post: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 21 | # Uses the secrets from the organisation for credentials 22 | - uses: actions/checkout@v2 23 | 24 | - name: Invoke workflow in another repo with inputs 25 | uses: benc-uk/workflow-dispatch@v1 26 | with: 27 | workflow: GuideConverter 28 | repo: OpenLiberty/cloud-hosted-guides 29 | token: ${{ secrets.GUIDECONVERSIONTOOL_PASSWORD }} 30 | inputs: '{ "branch": "${{ github.ref }}", "guide_name": "${{ github.event.repository.name }}" }' 31 | ref: "refs/heads/prod" 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven generated 2 | target/ 3 | 4 | # Eclipse generated 5 | .apt_generated/ 6 | .settings/ 7 | .project 8 | .classpath 9 | .factorypath 10 | MANIFEST.MF 11 | 12 | # MacOS system files 13 | .DS_Store 14 | 15 | # Asciidoc rendered 16 | README.html 17 | 18 | finish/resources/src/main/resources/keystore.jceks 19 | start/resources/src/main/resources/keystore.jceks 20 | temp/ 21 | /bin/ 22 | -------------------------------------------------------------------------------- /.travis.yml.disabled: -------------------------------------------------------------------------------- 1 | language: java 2 | before_script: 3 | - unset _JAVA_OPTIONS 4 | - cd finish/system 5 | - chmod +x ../../scripts/travisTest.sh 6 | script: 7 | - ../scripts/travisTest.sh 8 | after_script: 9 | - logsPath=$(find . -name "console.log" | sed "s/console.log//g"); 10 | - build=$(grep "Open Liberty" $logsPath/console.log | cut -d" " -f5 | cut -d")" -f1 ); 11 | - release=$( echo "$build" | cut -d'/' -f1); 12 | - number=$(echo "$build" | cut -d'/' -f2); 13 | - ol_jv=$(grep -i "version" $logsPath/console.log); 14 | - jv=$(printf '%s\n' "${ol_jv//$' on '/$'\n'}" | sed '2q;d'); 15 | - echo -e "\n"\ 16 | "\033[1;34m Open Liberty release:\033[0m\033[1;36m $release \033[0m \n"\ 17 | "\033[1;34m Open Liberty build number:\033[0m\033[1;36m $number \033[0m \n"\ 18 | "\033[1;34m Java version:\033[0m\033[1;36m $jv \033[0m \n" 19 | - cd $logsPath; 20 | - repo_name=$(echo "$TRAVIS_REPO_SLUG" | sed -e "s/\//-/g"); 21 | - if [ "$TRAVIS_TEST_RESULT" -eq 0 ]; then RESULT="passed"; else RESULT="failed"; fi; 22 | - echo -e "\033[1;34m result:\033[0m\033[1;36m $RESULT \033[0m \n" 23 | - serverlogsarchive="$repo_name-$TRAVIS_BUILD_NUMBER-$RESULT.zip"; 24 | - if [ "$TRAVIS_TEST_RESULT" -eq 0 ]; then echo skipped to zip $serverlogsarchive; else zip -r "$serverlogsarchive" .; fi; 25 | - if [ "$TRAVIS_TEST_RESULT" -eq 0 ]; then echo skipped upload; else curl -H "$JFROG_TOKEN" -T "$serverlogsarchive" "https://na.artifactory.swg-devops.com/artifactory/hyc-openliberty-guides-files-generic-local/"; fi; 26 | notifications: 27 | slack: 28 | template: 29 | - 'Build: <%{build_url}| %{build_number}> | Commit (<%{compare_url}|%{commit}>): 30 | %{commit_message}' 31 | - 'Repo@Branch: %{repository_slug}@%{branch}' 32 | - 'Author: %{author}' 33 | - 'Summary: %{result} in %{duration}' 34 | rooms: 35 | secure: mr3KuuI35DXbCA/ifU3wzsLYEbLriK6CAjdRrkt+ksfdeVHOMc8PvvCFcJovi9xSz/Oh/DWKBdqLwJ+bb1XUBUY1O5V0wTjczfIzIyXOiNy8pCrzwgGkmVVKCgkS1B+U4QX4+6vPl1yO8jThVEH4u4vpwcOIUQwWF23rRQa1rwiVlEorkloUvahYK4jeJ4K5/qU1f+ajX4bzkaTEGYY1sOFRyy6tUlAXupVAGjtyvZZRshiHmVzT+vNkR3OK9ImrOBg+tp1axSSSPuvNxSeqySjmgue3yL+F+hFiNfj6+FDwJm8r6O06aj0kbiuZBkulJuL76OPm6XajkmNdjbfxHlctUOwWLcz0dNT+6U24Ig+bdLOCxTGhQ8nzd3JDXauZdS9zyGoxqYbes4OvvJcrbkSOBYLILzPRDDpvEI8VE/VKxGtnkjf86K1dvbqvtDFeqIc9PFz+FGIIESQBi0nUPIOz6KLAKkBlR75XM133gJion97q3Qj85tSk7BJ7tX4rkSPjzxUsJ/gbMyk5ttHon2xdUFPObIXIZEGMJChQc+tMjmVEdrfjk4Rxm1ohz3FlXLmqMF+htaZWu8rtG1lUrZhdDjnyK8RrC1BHENDXHLCUTeo5ijQQD/PSypUSKemh3Zt8VZXznbjBORvGDDANjrtqhgOOKUCxuk3tlfjkipo= 36 | on_success: never 37 | on_failure: always 38 | branches: 39 | only: 40 | - master 41 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Open Liberty guides 2 | 3 | Anyone can contribute to the Open Liberty guides and we welcome your contributions! 4 | 5 | There are multiple ways to contribute: report bugs, fix bugs, contribute code, improve upon documentation, etc. 6 | 7 | ## Raising issues 8 | 9 | Please raise any bug reports in this [guide repository](../../issues). For new topics, large updates to existing guides, or general suggestions and ideas, report your issue in the [Open Liberty common guides repository](https://github.com/OpenLiberty/guides-common/issues). Be sure to search the list of open issues to see if your issue has already been raised. 10 | 11 | A good bug report makes it easy for everyone to understand what you were trying to do and what went wrong. Provide as much context as possible so we can try to recreate the issue. 12 | 13 | ## Contributions 14 | 15 | Contributing to an Open Liberty guide is simple. Each guide is maintained in its own GitHub repository. To contribute, just fork from the `prod` branch for your chosen guide. Then create a branch in your forked repository to include your contribution and open a pull request to the `staging` branch for the guide. 16 | Certify the originality of your work by following the [Developer Certificate of Origin (DCO)](https://developercertificate.org) approach and adding a line to the end of the Git commit message to sign your work: 17 | 18 | ```text 19 | Signed-off-by: Jane Williams 20 | ``` 21 | 22 | The sign-off is just a line at the end of the commit message that certifies that you wrote it or otherwise have the right to pass it on as an open source patch. 23 | 24 | Use your real name when you sign. We can't accept pseudonyms or anonymous contributions. 25 | 26 | Many Git UI tools have support for adding the `Signed-off-by` line to the end of your commit message. This line can be automatically added by the `git commit` command by using the `-s` option. 27 | 28 | The team is then notified and your contribution is reviewed according to the following process: 29 | 30 | 1. The team will review your change(s). 31 | - If there are further changes to be made, the team will request changes on the pull request. 32 | - If the team does not agree with the change, the PR will be closed with an explanation and suggestion for follow-up. 33 | 2. If the team approves, the team will merge your PR. A full Open Liberty staging site build will be run. 34 | 3. Based on the results of the build: 35 | - If further review is needed, we will let you know about a pending review from our team and discuss any necessary improvements that need to be made to your change(s). 36 | - If everything is successful, the team will publish your change(s) to the `prod` branch and update the Open Liberty production site, if necessary. 37 | 38 | ## Questions and concerns 39 | 40 | If you have any questions or concerns about the guides or about Open Liberty, you can visit [Gitter for Open Liberty](https://gitter.im/OpenLiberty/) and post your questions in the relevant rooms. You can also join the Open Liberty group on [Groups.io](https://groups.io/g/openliberty) to discuss any issues you have. 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Code and build scripts are licensed under the Eclipse Public License v2 2 | 3 | Documentation files (e.g. files with an adoc file extension) are licensed under 4 | Creative Commons Attribution-NoDerivatives 4.0 International (CC BY-ND 4.0) 5 | 6 | Eclipse Public License - v 2.0 7 | 8 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 9 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION 10 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 11 | 12 | 1. DEFINITIONS 13 | 14 | "Contribution" means: 15 | 16 | a) in the case of the initial Contributor, the initial content 17 | Distributed under this Agreement, and 18 | 19 | b) in the case of each subsequent Contributor: 20 | i) changes to the Program, and 21 | ii) additions to the Program; 22 | where such changes and/or additions to the Program originate from 23 | and are Distributed by that particular Contributor. A Contribution 24 | "originates" from a Contributor if it was added to the Program by 25 | such Contributor itself or anyone acting on such Contributor's behalf. 26 | Contributions do not include changes or additions to the Program that 27 | are not Modified Works. 28 | 29 | "Contributor" means any person or entity that Distributes the Program. 30 | 31 | "Licensed Patents" mean patent claims licensable by a Contributor which 32 | are necessarily infringed by the use or sale of its Contribution alone 33 | or when combined with the Program. 34 | 35 | "Program" means the Contributions Distributed in accordance with this 36 | Agreement. 37 | 38 | "Recipient" means anyone who receives the Program under this Agreement 39 | or any Secondary License (as applicable), including Contributors. 40 | 41 | "Derivative Works" shall mean any work, whether in Source Code or other 42 | form, that is based on (or derived from) the Program and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. 45 | 46 | "Modified Works" shall mean any work in Source Code or other form that 47 | results from an addition to, deletion from, or modification of the 48 | contents of the Program, including, for purposes of clarity any new file 49 | in Source Code form that contains any contents of the Program. Modified 50 | Works shall not include works that contain only declarations, 51 | interfaces, types, classes, structures, or files of the Program solely 52 | in each case in order to link to, bind by name, or subclass the Program 53 | or Modified Works thereof. 54 | 55 | "Distribute" means the acts of a) distributing or b) making available 56 | in any manner that enables the transfer of a copy. 57 | 58 | "Source Code" means the form of a Program preferred for making 59 | modifications, including but not limited to software source code, 60 | documentation source, and configuration files. 61 | 62 | "Secondary License" means either the GNU General Public License, 63 | Version 2.0, or any later versions of that license, including any 64 | exceptions or additional permissions as identified by the initial 65 | Contributor. 66 | 67 | 2. GRANT OF RIGHTS 68 | 69 | a) Subject to the terms of this Agreement, each Contributor hereby 70 | grants Recipient a non-exclusive, worldwide, royalty-free copyright 71 | license to reproduce, prepare Derivative Works of, publicly display, 72 | publicly perform, Distribute and sublicense the Contribution of such 73 | Contributor, if any, and such Derivative Works. 74 | 75 | b) Subject to the terms of this Agreement, each Contributor hereby 76 | grants Recipient a non-exclusive, worldwide, royalty-free patent 77 | license under Licensed Patents to make, use, sell, offer to sell, 78 | import and otherwise transfer the Contribution of such Contributor, 79 | if any, in Source Code or other form. This patent license shall 80 | apply to the combination of the Contribution and the Program if, at 81 | the time the Contribution is added by the Contributor, such addition 82 | of the Contribution causes such combination to be covered by the 83 | Licensed Patents. The patent license shall not apply to any other 84 | combinations which include the Contribution. No hardware per se is 85 | licensed hereunder. 86 | 87 | c) Recipient understands that although each Contributor grants the 88 | licenses to its Contributions set forth herein, no assurances are 89 | provided by any Contributor that the Program does not infringe the 90 | patent or other intellectual property rights of any other entity. 91 | Each Contributor disclaims any liability to Recipient for claims 92 | brought by any other entity based on infringement of intellectual 93 | property rights or otherwise. As a condition to exercising the 94 | rights and licenses granted hereunder, each Recipient hereby 95 | assumes sole responsibility to secure any other intellectual 96 | property rights needed, if any. For example, if a third party 97 | patent license is required to allow Recipient to Distribute the 98 | Program, it is Recipient's responsibility to acquire that license 99 | before distributing the Program. 100 | 101 | d) Each Contributor represents that to its knowledge it has 102 | sufficient copyright rights in its Contribution, if any, to grant 103 | the copyright license set forth in this Agreement. 104 | 105 | e) Notwithstanding the terms of any Secondary License, no 106 | Contributor makes additional grants to any Recipient (other than 107 | those set forth in this Agreement) as a result of such Recipient's 108 | receipt of the Program under the terms of a Secondary License 109 | (if permitted under the terms of Section 3). 110 | 111 | 3. REQUIREMENTS 112 | 113 | 3.1 If a Contributor Distributes the Program in any form, then: 114 | 115 | a) the Program must also be made available as Source Code, in 116 | accordance with section 3.2, and the Contributor must accompany 117 | the Program with a statement that the Source Code for the Program 118 | is available under this Agreement, and informs Recipients how to 119 | obtain it in a reasonable manner on or through a medium customarily 120 | used for software exchange; and 121 | 122 | b) the Contributor may Distribute the Program under a license 123 | different than this Agreement, provided that such license: 124 | i) effectively disclaims on behalf of all other Contributors all 125 | warranties and conditions, express and implied, including 126 | warranties or conditions of title and non-infringement, and 127 | implied warranties or conditions of merchantability and fitness 128 | for a particular purpose; 129 | 130 | ii) effectively excludes on behalf of all other Contributors all 131 | liability for damages, including direct, indirect, special, 132 | incidental and consequential damages, such as lost profits; 133 | 134 | iii) does not attempt to limit or alter the recipients' rights 135 | in the Source Code under section 3.2; and 136 | 137 | iv) requires any subsequent distribution of the Program by any 138 | party to be under a license that satisfies the requirements 139 | of this section 3. 140 | 141 | 3.2 When the Program is Distributed as Source Code: 142 | 143 | a) it must be made available under this Agreement, or if the 144 | Program (i) is combined with other material in a separate file or 145 | files made available under a Secondary License, and (ii) the initial 146 | Contributor attached to the Source Code the notice described in 147 | Exhibit A of this Agreement, then the Program may be made available 148 | under the terms of such Secondary Licenses, and 149 | 150 | b) a copy of this Agreement must be included with each copy of 151 | the Program. 152 | 153 | 3.3 Contributors may not remove or alter any copyright, patent, 154 | trademark, attribution notices, disclaimers of warranty, or limitations 155 | of liability ("notices") contained within the Program from any copy of 156 | the Program which they Distribute, provided that Contributors may add 157 | their own appropriate notices. 158 | 159 | 4. COMMERCIAL DISTRIBUTION 160 | 161 | Commercial distributors of software may accept certain responsibilities 162 | with respect to end users, business partners and the like. While this 163 | license is intended to facilitate the commercial use of the Program, 164 | the Contributor who includes the Program in a commercial product 165 | offering should do so in a manner which does not create potential 166 | liability for other Contributors. Therefore, if a Contributor includes 167 | the Program in a commercial product offering, such Contributor 168 | ("Commercial Contributor") hereby agrees to defend and indemnify every 169 | other Contributor ("Indemnified Contributor") against any losses, 170 | damages and costs (collectively "Losses") arising from claims, lawsuits 171 | and other legal actions brought by a third party against the Indemnified 172 | Contributor to the extent caused by the acts or omissions of such 173 | Commercial Contributor in connection with its distribution of the Program 174 | in a commercial product offering. The obligations in this section do not 175 | apply to any claims or Losses relating to any actual or alleged 176 | intellectual property infringement. In order to qualify, an Indemnified 177 | Contributor must: a) promptly notify the Commercial Contributor in 178 | writing of such claim, and b) allow the Commercial Contributor to control, 179 | and cooperate with the Commercial Contributor in, the defense and any 180 | related settlement negotiations. The Indemnified Contributor may 181 | participate in any such claim at its own expense. 182 | 183 | For example, a Contributor might include the Program in a commercial 184 | product offering, Product X. That Contributor is then a Commercial 185 | Contributor. If that Commercial Contributor then makes performance 186 | claims, or offers warranties related to Product X, those performance 187 | claims and warranties are such Commercial Contributor's responsibility 188 | alone. Under this section, the Commercial Contributor would have to 189 | defend claims against the other Contributors related to those performance 190 | claims and warranties, and if a court requires any other Contributor to 191 | pay any damages as a result, the Commercial Contributor must pay 192 | those damages. 193 | 194 | 5. NO WARRANTY 195 | 196 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 197 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" 198 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 199 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF 200 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 201 | PURPOSE. Each Recipient is solely responsible for determining the 202 | appropriateness of using and distributing the Program and assumes all 203 | risks associated with its exercise of rights under this Agreement, 204 | including but not limited to the risks and costs of program errors, 205 | compliance with applicable laws, damage to or loss of data, programs 206 | or equipment, and unavailability or interruption of operations. 207 | 208 | 6. DISCLAIMER OF LIABILITY 209 | 210 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 211 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS 212 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 213 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 214 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 215 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 216 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 217 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE 218 | POSSIBILITY OF SUCH DAMAGES. 219 | 220 | 7. GENERAL 221 | 222 | If any provision of this Agreement is invalid or unenforceable under 223 | applicable law, it shall not affect the validity or enforceability of 224 | the remainder of the terms of this Agreement, and without further 225 | action by the parties hereto, such provision shall be reformed to the 226 | minimum extent necessary to make such provision valid and enforceable. 227 | 228 | If Recipient institutes patent litigation against any entity 229 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 230 | Program itself (excluding combinations of the Program with other software 231 | or hardware) infringes such Recipient's patent(s), then such Recipient's 232 | rights granted under Section 2(b) shall terminate as of the date such 233 | litigation is filed. 234 | 235 | All Recipient's rights under this Agreement shall terminate if it 236 | fails to comply with any of the material terms or conditions of this 237 | Agreement and does not cure such failure in a reasonable period of 238 | time after becoming aware of such noncompliance. If all Recipient's 239 | rights under this Agreement terminate, Recipient agrees to cease use 240 | and distribution of the Program as soon as reasonably practicable. 241 | However, Recipient's obligations under this Agreement and any licenses 242 | granted by Recipient relating to the Program shall continue and survive. 243 | 244 | Everyone is permitted to copy and distribute copies of this Agreement, 245 | but in order to avoid inconsistency the Agreement is copyrighted and 246 | may only be modified in the following manner. The Agreement Steward 247 | reserves the right to publish new versions (including revisions) of 248 | this Agreement from time to time. No one other than the Agreement 249 | Steward has the right to modify this Agreement. The Eclipse Foundation 250 | is the initial Agreement Steward. The Eclipse Foundation may assign the 251 | responsibility to serve as the Agreement Steward to a suitable separate 252 | entity. Each new version of the Agreement will be given a distinguishing 253 | version number. The Program (including Contributions) may always be 254 | Distributed subject to the version of the Agreement under which it was 255 | received. In addition, after a new version of the Agreement is published, 256 | Contributor may elect to Distribute the Program (including its 257 | Contributions) under the new version. 258 | 259 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient 260 | receives no rights or licenses to the intellectual property of any 261 | Contributor under this Agreement, whether expressly, by implication, 262 | estoppel or otherwise. All rights in the Program not expressly granted 263 | under this Agreement are reserved. Nothing in this Agreement is intended 264 | to be enforceable by any entity that is not a Contributor or Recipient. 265 | No third-party beneficiary rights are created under this Agreement. 266 | 267 | Exhibit A - Form of Secondary Licenses Notice 268 | 269 | "This Source Code may also be made available under the following 270 | Secondary Licenses when the conditions for such availability set forth 271 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), 272 | version(s), and exceptions or additional permissions here}." 273 | 274 | Simply including a copy of this Agreement, including this Exhibit A 275 | is not sufficient to license the Source Code under Secondary Licenses. 276 | 277 | If it is not possible or desirable to put the notice in a particular 278 | file, then You may include the notice in a location (such as a LICENSE 279 | file in a relevant directory) where a recipient would be likely to 280 | look for such a notice. 281 | 282 | You may add additional accurate notices of copyright ownership. 283 | 284 | -------------------------------------------------------------------------------- 285 | 286 | Attribution-NoDerivatives 4.0 International 287 | 288 | ======================================================================= 289 | 290 | Creative Commons Corporation ("Creative Commons") is not a law firm and 291 | does not provide legal services or legal advice. Distribution of 292 | Creative Commons public licenses does not create a lawyer-client or 293 | other relationship. Creative Commons makes its licenses and related 294 | information available on an "as-is" basis. Creative Commons gives no 295 | warranties regarding its licenses, any material licensed under their 296 | terms and conditions, or any related information. Creative Commons 297 | disclaims all liability for damages resulting from their use to the 298 | fullest extent possible. 299 | 300 | Using Creative Commons Public Licenses 301 | 302 | Creative Commons public licenses provide a standard set of terms and 303 | conditions that creators and other rights holders may use to share 304 | original works of authorship and other material subject to copyright 305 | and certain other rights specified in the public license below. The 306 | following considerations are for informational purposes only, are not 307 | exhaustive, and do not form part of our licenses. 308 | 309 | Considerations for licensors: Our public licenses are 310 | intended for use by those authorized to give the public 311 | permission to use material in ways otherwise restricted by 312 | copyright and certain other rights. Our licenses are 313 | irrevocable. Licensors should read and understand the terms 314 | and conditions of the license they choose before applying it. 315 | Licensors should also secure all rights necessary before 316 | applying our licenses so that the public can reuse the 317 | material as expected. Licensors should clearly mark any 318 | material not subject to the license. This includes other CC- 319 | licensed material, or material used under an exception or 320 | limitation to copyright. More considerations for licensors: 321 | wiki.creativecommons.org/Considerations_for_licensors 322 | 323 | Considerations for the public: By using one of our public 324 | licenses, a licensor grants the public permission to use the 325 | licensed material under specified terms and conditions. If 326 | the licensor's permission is not necessary for any reason--for 327 | example, because of any applicable exception or limitation to 328 | copyright--then that use is not regulated by the license. Our 329 | licenses grant only permissions under copyright and certain 330 | other rights that a licensor has authority to grant. Use of 331 | the licensed material may still be restricted for other 332 | reasons, including because others have copyright or other 333 | rights in the material. A licensor may make special requests, 334 | such as asking that all changes be marked or described. 335 | Although not required by our licenses, you are encouraged to 336 | respect those requests where reasonable. More_considerations 337 | for the public: 338 | wiki.creativecommons.org/Considerations_for_licensees 339 | 340 | 341 | ======================================================================= 342 | 343 | Creative Commons Attribution-NoDerivatives 4.0 International Public 344 | License 345 | 346 | By exercising the Licensed Rights (defined below), You accept and agree 347 | to be bound by the terms and conditions of this Creative Commons 348 | Attribution-NoDerivatives 4.0 International Public License ("Public 349 | License"). To the extent this Public License may be interpreted as a 350 | contract, You are granted the Licensed Rights in consideration of Your 351 | acceptance of these terms and conditions, and the Licensor grants You 352 | such rights in consideration of benefits the Licensor receives from 353 | making the Licensed Material available under these terms and 354 | conditions. 355 | 356 | 357 | Section 1 -- Definitions. 358 | 359 | a. Adapted Material means material subject to Copyright and Similar 360 | Rights that is derived from or based upon the Licensed Material 361 | and in which the Licensed Material is translated, altered, 362 | arranged, transformed, or otherwise modified in a manner requiring 363 | permission under the Copyright and Similar Rights held by the 364 | Licensor. For purposes of this Public License, where the Licensed 365 | Material is a musical work, performance, or sound recording, 366 | Adapted Material is always produced where the Licensed Material is 367 | synched in timed relation with a moving image. 368 | 369 | b. Copyright and Similar Rights means copyright and/or similar rights 370 | closely related to copyright including, without limitation, 371 | performance, broadcast, sound recording, and Sui Generis Database 372 | Rights, without regard to how the rights are labeled or 373 | categorized. For purposes of this Public License, the rights 374 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 375 | Rights. 376 | 377 | c. Effective Technological Measures means those measures that, in the 378 | absence of proper authority, may not be circumvented under laws 379 | fulfilling obligations under Article 11 of the WIPO Copyright 380 | Treaty adopted on December 20, 1996, and/or similar international 381 | agreements. 382 | 383 | d. Exceptions and Limitations means fair use, fair dealing, and/or 384 | any other exception or limitation to Copyright and Similar Rights 385 | that applies to Your use of the Licensed Material. 386 | 387 | e. Licensed Material means the artistic or literary work, database, 388 | or other material to which the Licensor applied this Public 389 | License. 390 | 391 | f. Licensed Rights means the rights granted to You subject to the 392 | terms and conditions of this Public License, which are limited to 393 | all Copyright and Similar Rights that apply to Your use of the 394 | Licensed Material and that the Licensor has authority to license. 395 | 396 | g. Licensor means the individual(s) or entity(ies) granting rights 397 | under this Public License. 398 | 399 | h. Share means to provide material to the public by any means or 400 | process that requires permission under the Licensed Rights, such 401 | as reproduction, public display, public performance, distribution, 402 | dissemination, communication, or importation, and to make material 403 | available to the public including in ways that members of the 404 | public may access the material from a place and at a time 405 | individually chosen by them. 406 | 407 | i. Sui Generis Database Rights means rights other than copyright 408 | resulting from Directive 96/9/EC of the European Parliament and of 409 | the Council of 11 March 1996 on the legal protection of databases, 410 | as amended and/or succeeded, as well as other essentially 411 | equivalent rights anywhere in the world. 412 | 413 | j. You means the individual or entity exercising the Licensed Rights 414 | under this Public License. Your has a corresponding meaning. 415 | 416 | 417 | Section 2 -- Scope. 418 | 419 | a. License grant. 420 | 421 | 1. Subject to the terms and conditions of this Public License, 422 | the Licensor hereby grants You a worldwide, royalty-free, 423 | non-sublicensable, non-exclusive, irrevocable license to 424 | exercise the Licensed Rights in the Licensed Material to: 425 | 426 | a. reproduce and Share the Licensed Material, in whole or 427 | in part; and 428 | 429 | b. produce and reproduce, but not Share, Adapted Material. 430 | 431 | 2. Exceptions and Limitations. For the avoidance of doubt, where 432 | Exceptions and Limitations apply to Your use, this Public 433 | License does not apply, and You do not need to comply with 434 | its terms and conditions. 435 | 436 | 3. Term. The term of this Public License is specified in Section 437 | 6(a). 438 | 439 | 4. Media and formats; technical modifications allowed. The 440 | Licensor authorizes You to exercise the Licensed Rights in 441 | all media and formats whether now known or hereafter created, 442 | and to make technical modifications necessary to do so. The 443 | Licensor waives and/or agrees not to assert any right or 444 | authority to forbid You from making technical modifications 445 | necessary to exercise the Licensed Rights, including 446 | technical modifications necessary to circumvent Effective 447 | Technological Measures. For purposes of this Public License, 448 | simply making modifications authorized by this Section 2(a) 449 | (4) never produces Adapted Material. 450 | 451 | 5. Downstream recipients. 452 | 453 | a. Offer from the Licensor -- Licensed Material. Every 454 | recipient of the Licensed Material automatically 455 | receives an offer from the Licensor to exercise the 456 | Licensed Rights under the terms and conditions of this 457 | Public License. 458 | 459 | b. No downstream restrictions. You may not offer or impose 460 | any additional or different terms or conditions on, or 461 | apply any Effective Technological Measures to, the 462 | Licensed Material if doing so restricts exercise of the 463 | Licensed Rights by any recipient of the Licensed 464 | Material. 465 | 466 | 6. No endorsement. Nothing in this Public License constitutes or 467 | may be construed as permission to assert or imply that You 468 | are, or that Your use of the Licensed Material is, connected 469 | with, or sponsored, endorsed, or granted official status by, 470 | the Licensor or others designated to receive attribution as 471 | provided in Section 3(a)(1)(A)(i). 472 | 473 | b. Other rights. 474 | 475 | 1. Moral rights, such as the right of integrity, are not 476 | licensed under this Public License, nor are publicity, 477 | privacy, and/or other similar personality rights; however, to 478 | the extent possible, the Licensor waives and/or agrees not to 479 | assert any such rights held by the Licensor to the limited 480 | extent necessary to allow You to exercise the Licensed 481 | Rights, but not otherwise. 482 | 483 | 2. Patent and trademark rights are not licensed under this 484 | Public License. 485 | 486 | 3. To the extent possible, the Licensor waives any right to 487 | collect royalties from You for the exercise of the Licensed 488 | Rights, whether directly or through a collecting society 489 | under any voluntary or waivable statutory or compulsory 490 | licensing scheme. In all other cases the Licensor expressly 491 | reserves any right to collect such royalties. 492 | 493 | 494 | Section 3 -- License Conditions. 495 | 496 | Your exercise of the Licensed Rights is expressly made subject to the 497 | following conditions. 498 | 499 | a. Attribution. 500 | 501 | 1. If You Share the Licensed Material, You must: 502 | 503 | a. retain the following if it is supplied by the Licensor 504 | with the Licensed Material: 505 | 506 | i. identification of the creator(s) of the Licensed 507 | Material and any others designated to receive 508 | attribution, in any reasonable manner requested by 509 | the Licensor (including by pseudonym if 510 | designated); 511 | 512 | ii. a copyright notice; 513 | 514 | iii. a notice that refers to this Public License; 515 | 516 | iv. a notice that refers to the disclaimer of 517 | warranties; 518 | 519 | v. a URI or hyperlink to the Licensed Material to the 520 | extent reasonably practicable; 521 | 522 | b. indicate if You modified the Licensed Material and 523 | retain an indication of any previous modifications; and 524 | 525 | c. indicate the Licensed Material is licensed under this 526 | Public License, and include the text of, or the URI or 527 | hyperlink to, this Public License. 528 | 529 | For the avoidance of doubt, You do not have permission under 530 | this Public License to Share Adapted Material. 531 | 532 | 2. You may satisfy the conditions in Section 3(a)(1) in any 533 | reasonable manner based on the medium, means, and context in 534 | which You Share the Licensed Material. For example, it may be 535 | reasonable to satisfy the conditions by providing a URI or 536 | hyperlink to a resource that includes the required 537 | information. 538 | 539 | 3. If requested by the Licensor, You must remove any of the 540 | information required by Section 3(a)(1)(A) to the extent 541 | reasonably practicable. 542 | 543 | 544 | Section 4 -- Sui Generis Database Rights. 545 | 546 | Where the Licensed Rights include Sui Generis Database Rights that 547 | apply to Your use of the Licensed Material: 548 | 549 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 550 | to extract, reuse, reproduce, and Share all or a substantial 551 | portion of the contents of the database, provided You do not Share 552 | Adapted Material; 553 | b. if You include all or a substantial portion of the database 554 | contents in a database in which You have Sui Generis Database 555 | Rights, then the database in which You have Sui Generis Database 556 | Rights (but not its individual contents) is Adapted Material; and 557 | c. You must comply with the conditions in Section 3(a) if You Share 558 | all or a substantial portion of the contents of the database. 559 | 560 | For the avoidance of doubt, this Section 4 supplements and does not 561 | replace Your obligations under this Public License where the Licensed 562 | Rights include other Copyright and Similar Rights. 563 | 564 | 565 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 566 | 567 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 568 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 569 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 570 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 571 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 572 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 573 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 574 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 575 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 576 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 577 | 578 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 579 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 580 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 581 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 582 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 583 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 584 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 585 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 586 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 587 | 588 | c. The disclaimer of warranties and limitation of liability provided 589 | above shall be interpreted in a manner that, to the extent 590 | possible, most closely approximates an absolute disclaimer and 591 | waiver of all liability. 592 | 593 | 594 | Section 6 -- Term and Termination. 595 | 596 | a. This Public License applies for the term of the Copyright and 597 | Similar Rights licensed here. However, if You fail to comply with 598 | this Public License, then Your rights under this Public License 599 | terminate automatically. 600 | 601 | b. Where Your right to use the Licensed Material has terminated under 602 | Section 6(a), it reinstates: 603 | 604 | 1. automatically as of the date the violation is cured, provided 605 | it is cured within 30 days of Your discovery of the 606 | violation; or 607 | 608 | 2. upon express reinstatement by the Licensor. 609 | 610 | For the avoidance of doubt, this Section 6(b) does not affect any 611 | right the Licensor may have to seek remedies for Your violations 612 | of this Public License. 613 | 614 | c. For the avoidance of doubt, the Licensor may also offer the 615 | Licensed Material under separate terms or conditions or stop 616 | distributing the Licensed Material at any time; however, doing so 617 | will not terminate this Public License. 618 | 619 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 620 | License. 621 | 622 | 623 | Section 7 -- Other Terms and Conditions. 624 | 625 | a. The Licensor shall not be bound by any additional or different 626 | terms or conditions communicated by You unless expressly agreed. 627 | 628 | b. Any arrangements, understandings, or agreements regarding the 629 | Licensed Material not stated herein are separate from and 630 | independent of the terms and conditions of this Public License. 631 | 632 | 633 | Section 8 -- Interpretation. 634 | 635 | a. For the avoidance of doubt, this Public License does not, and 636 | shall not be interpreted to, reduce, limit, restrict, or impose 637 | conditions on any use of the Licensed Material that could lawfully 638 | be made without permission under this Public License. 639 | 640 | b. To the extent possible, if any provision of this Public License is 641 | deemed unenforceable, it shall be automatically reformed to the 642 | minimum extent necessary to make it enforceable. If the provision 643 | cannot be reformed, it shall be severed from this Public License 644 | without affecting the enforceability of the remaining terms and 645 | conditions. 646 | 647 | c. No term or condition of this Public License will be waived and no 648 | failure to comply consented to unless expressly agreed to by the 649 | Licensor. 650 | 651 | d. Nothing in this Public License constitutes or may be interpreted 652 | as a limitation upon, or waiver of, any privileges and immunities 653 | that apply to the Licensor or You, including from the legal 654 | processes of any jurisdiction or authority. 655 | 656 | ======================================================================= 657 | 658 | Creative Commons is not a party to its public 659 | licenses. Notwithstanding, Creative Commons may elect to apply one of 660 | its public licenses to material it publishes and in those instances 661 | will be considered the “Licensor.” The text of the Creative Commons 662 | public licenses is dedicated to the public domain under the CC0 Public 663 | Domain Dedication. Except for the limited purpose of indicating that 664 | material is shared under a Creative Commons public license or as 665 | otherwise permitted by the Creative Commons policies published at 666 | creativecommons.org/policies, Creative Commons does not authorize the 667 | use of the trademark "Creative Commons" or any other trademark or logo 668 | of Creative Commons without its prior written consent including, 669 | without limitation, in connection with any unauthorized modifications 670 | to any of its public licenses or any other arrangements, 671 | understandings, or agreements concerning use of licensed material. For 672 | the avoidance of doubt, this paragraph does not form part of the 673 | public licenses. 674 | 675 | Creative Commons may be contacted at creativecommons.org. 676 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, 2025 IBM Corporation and others. 2 | // Licensed under Creative Commons Attribution-NoDerivatives 3 | // 4.0 International (CC BY-ND 4.0) 4 | // https://creativecommons.org/licenses/by-nd/4.0/ 5 | // 6 | // Contributors: 7 | // IBM Corporation 8 | :projectid: microprofile-jwt 9 | :page-layout: guide-multipane 10 | :page-duration: 25 minutes 11 | :page-releasedate: 2018-03-09 12 | :page-guide-category: microprofile 13 | :page-essential: false 14 | :page-description: Learn how to control user and role access to microservices by using MicroProfile JWT. 15 | :page-tags: ["microprofile", "security"] 16 | :page-permalink: /guides/{projectid} 17 | :imagesdir: /img/guide/{projectid} 18 | :page-related-guides: ['social-media-login', 'rest-intro', 'cdi-intro'] 19 | :common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod 20 | :source-highlighter: prettify 21 | :page-seo-title: Securing Java microservices with Eclipse MicroProfile JSON Web Token (MicroProfile JWT) 22 | :page-seo-description: A getting started tutorial and an example on how to secure Java microservices to authenticate users and authorize access by validating JSON Web Tokens (JWT) using Eclipse MicroProfile JWT. 23 | :guide-author: Open Liberty 24 | = Securing microservices with JSON Web Tokens 25 | 26 | [.hidden] 27 | NOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website^]. 28 | 29 | You'll explore how to control user and role access to microservices with MicroProfile JSON Web Token (MicroProfile JWT). 30 | 31 | // ================================================================================================= 32 | // What you'll learn 33 | // ================================================================================================= 34 | 35 | == What you'll learn 36 | 37 | You will add token-based authentication mechanisms to authenticate, authorize, and verify users by implementing MicroProfile JWT in the `system` microservice. 38 | 39 | A JSON Web Token (JWT) is a self-contained token that is designed to securely transmit information as a JSON object. The information in this JSON object is digitally signed and can be trusted and verified by the recipient. 40 | 41 | For microservices, a token-based authentication mechanism offers a lightweight way for security controls and security tokens to propagate user identities across different services. JSON Web Token is becoming the most common token format because it follows well-defined and known standards. 42 | 43 | MicroProfile JWT standards define the required format of JWT for authentication and authorization. The standards also map JWT claims to various Jakarta EE container APIs and make the set of claims available through getter methods. 44 | 45 | In this guide, the application uses JWTs to authenticate a user, allowing them to make authorized requests to a secure backend service. 46 | 47 | You will be working with two services, a `frontend` service and a secure `system` backend service. The `frontend` service logs a user in, builds a JWT, and makes authorized requests to the secure `system` service for JVM system properties. The following diagram depicts the application that is used in this guide: 48 | 49 | image::JWT_Diagram.png[JWT frontend and system services, width=490, height=654, align="center"] 50 | 51 | The user signs in to the `frontend` service with a username and a password, at which point a JWT is created. The `frontend` service then makes requests, with the JWT included, to the `system` backend service. The secure `system` service verifies the JWT to ensure that the request came from the authorized `frontend` service. After the JWT is validated, the information in the claims, such as the user's role, can be trusted and used to determine which system properties the user has access to. 52 | 53 | To learn more about JSON Web Tokens, check out the https://jwt.io/introduction/[jwt.io website^]. If you want to learn more about how JWTs can be used for user authentication and authorization, check out the Open Liberty https://openliberty.io/docs/latest/single-sign-on.html[Single Sign-on documentation^]. 54 | 55 | // ================================================================================================= 56 | // Getting started 57 | // ================================================================================================= 58 | [role='command'] 59 | include::{common-includes}/gitclone.adoc[] 60 | 61 | === Try what you'll build 62 | 63 | The `finish` directory contains the finished JWT security implementation for the services in the application. Try the finished application before you build your own. 64 | 65 | To try out the application, run the following commands to navigate to the `finish` directory and deploy the `frontend` service to Open Liberty: 66 | 67 | include::{common-includes}/os-tabs.adoc[] 68 | 69 | [.tab_content.windows_section] 70 | -- 71 | [role='command'] 72 | ``` 73 | cd finish 74 | mvnw.cmd -pl frontend liberty:run 75 | ``` 76 | -- 77 | 78 | [.tab_content.mac_section] 79 | -- 80 | [role='command'] 81 | ``` 82 | cd finish 83 | ./mvnw -pl frontend liberty:run 84 | ``` 85 | -- 86 | 87 | [.tab_content.linux_section] 88 | -- 89 | [role='command'] 90 | ``` 91 | cd finish 92 | ./mvnw -pl frontend liberty:run 93 | ``` 94 | -- 95 | 96 | Open another command-line session and run the following commands to navigate to the `finish` directory and deploy the `system` service to Open Liberty: 97 | 98 | include::{common-includes}/os-tabs.adoc[] 99 | 100 | [.tab_content.windows_section] 101 | -- 102 | [role='command'] 103 | ``` 104 | cd finish 105 | mvnw.cmd -pl system liberty:run 106 | ``` 107 | -- 108 | 109 | [.tab_content.mac_section] 110 | -- 111 | [role='command'] 112 | ``` 113 | cd finish 114 | ./mvnw -pl system liberty:run 115 | ``` 116 | -- 117 | 118 | [.tab_content.linux_section] 119 | -- 120 | [role='command'] 121 | ``` 122 | cd finish 123 | ./mvnw -pl system liberty:run 124 | ``` 125 | -- 126 | 127 | After you see the following message in both command-line sessions, both of your services are ready: 128 | 129 | [source, role="no_copy"] 130 | ---- 131 | The defaultServer server is ready to run a smarter planet. 132 | ---- 133 | 134 | // static guide instructions: 135 | ifndef::cloud-hosted[] 136 | In your browser, go to the front-end web application endpoint at http://localhost:9090/login.jsf[http://localhost:9090/login.jsf^]. From here, you can log in to the application with the form-based login. 137 | endif::[] 138 | 139 | // cloud-hosted guide instructions: 140 | ifdef::cloud-hosted[] 141 | To launch the front-end web application, click the following button. From here, you can log in to the application with the form-based login. 142 | ::startApplication{port="9090" display="external" name="Launch Application" route="/login.jsf"} 143 | endif::[] 144 | 145 | Log in with one of the following usernames and its corresponding password: 146 | 147 | [cols="<35, ^200, ^200"] 148 | |=== 149 | | *Username* | *Password* | *Role* 150 | | bob | bobpwd | admin, user 151 | | alice | alicepwd | user 152 | | carl | carlpwd | user 153 | |=== 154 | 155 | You're redirected to a page that displays information that the front end requested from the `system` service, such as the system username. If you log in as an `admin`, you can also see the current OS. Click `Log Out` and log in as a `user`. You'll see the message `You are not authorized to access this system property` because the `user` role doesn't have sufficient privileges to view current OS information. 156 | 157 | Additionally, the `groups` claim of the JWT is read by the `system` service and requested by the front end to be displayed. 158 | 159 | // static guide instructions: 160 | ifndef::cloud-hosted[] 161 | You can try accessing these services without a JWT by going to the https://localhost:8443/system/properties/os[https://localhost:8443/system/properties/os^] `system` endpoint in your browser. You get a blank screen and aren't given access because you didn't supply a valid JWT with the request. The following error also appears in the command-line session of the `system` service: 162 | endif::[] 163 | 164 | // cloud-hosted guide instructions: 165 | ifdef::cloud-hosted[] 166 | You can try accessing these services without a JWT by going to the ***system*** endpoint. Open another command-line session by selecting **Terminal** > **New Terminal** from the menu of the IDE. Run the following curl command from the terminal in the IDE: 167 | ```bash 168 | curl -k https://localhost:8443/system/properties/os 169 | ``` 170 | 171 | The response is empty because you don't have access. Access is granted if a valid JWT is sent with the request. The following error also appears in the command-line session of the ***system*** service: 172 | endif::[] 173 | 174 | [source, role="no_copy"] 175 | ---- 176 | [ERROR] CWWKS5522E: The MicroProfile JWT feature cannot perform authentication because a MicroProfile JWT cannot be found in the request. 177 | ---- 178 | 179 | When you are done with the application, stop both the `frontend` and `system` services by pressing `CTRL+C` in the command-line sessions where you ran them. Alternatively, you can run the following goals from the `finish` directory in another command-line session: 180 | 181 | include::{common-includes}/os-tabs.adoc[] 182 | 183 | [.tab_content.windows_section] 184 | -- 185 | [role='command'] 186 | ``` 187 | mvnw.cmd -pl system liberty:stop 188 | mvnw.cmd -pl frontend liberty:stop 189 | ``` 190 | -- 191 | 192 | [.tab_content.mac_section] 193 | -- 194 | [role='command'] 195 | ``` 196 | ./mvnw -pl system liberty:stop 197 | ./mvnw -pl frontend liberty:stop 198 | ``` 199 | -- 200 | 201 | [.tab_content.linux_section] 202 | -- 203 | [role='command'] 204 | ``` 205 | ./mvnw -pl system liberty:stop 206 | ./mvnw -pl frontend liberty:stop 207 | ``` 208 | -- 209 | 210 | // ================================================================================================= 211 | // Creating the secure system service 212 | // ================================================================================================= 213 | 214 | == Creating the secure system service 215 | 216 | // static guide instructions: 217 | ifndef::cloud-hosted[] 218 | Navigate to the `start` directory to begin. 219 | endif::[] 220 | 221 | // cloud-hosted guide instructions: 222 | ifdef::cloud-hosted[] 223 | To begin, run the following command to navigate to the ***start*** directory: 224 | ```bash 225 | cd /home/project/guide-microprofile-jwt/start 226 | ``` 227 | endif::[] 228 | 229 | When you run Open Liberty in https://openliberty.io/docs/latest/development-mode.html[dev mode^], dev mode listens for file changes and automatically recompiles and deploys your updates whenever you save a new change. Run the following command to start the `frontend` service in dev mode: 230 | 231 | include::{common-includes}/os-tabs.adoc[] 232 | 233 | [.tab_content.windows_section] 234 | -- 235 | [role='command'] 236 | ``` 237 | mvnw.cmd -pl frontend liberty:dev 238 | ``` 239 | -- 240 | 241 | [.tab_content.mac_section] 242 | -- 243 | [role='command'] 244 | ``` 245 | ./mvnw -pl frontend liberty:dev 246 | ``` 247 | -- 248 | 249 | [.tab_content.linux_section] 250 | -- 251 | [role='command'] 252 | ``` 253 | ./mvnw -pl frontend liberty:dev 254 | ``` 255 | -- 256 | 257 | Open another command-line session and run the following command to start the `system` service in dev mode: 258 | 259 | include::{common-includes}/os-tabs.adoc[] 260 | 261 | [.tab_content.windows_section] 262 | -- 263 | [role='command'] 264 | ``` 265 | mvnw.cmd -pl system liberty:dev 266 | ``` 267 | -- 268 | 269 | [.tab_content.mac_section] 270 | -- 271 | [role='command'] 272 | ``` 273 | ./mvnw -pl system liberty:dev 274 | ``` 275 | -- 276 | 277 | [.tab_content.linux_section] 278 | -- 279 | [role='command'] 280 | ``` 281 | ./mvnw -pl system liberty:dev 282 | ``` 283 | -- 284 | 285 | After you see the following message, your Liberty instance is ready in dev mode: 286 | 287 | [source, role="no_copy"] 288 | ---- 289 | ************************************************************** 290 | * Liberty is running in dev mode. 291 | ---- 292 | 293 | The `system` service provides endpoints for the `frontend` service to use to request system properties. This service is secure and requires a valid JWT to be included in requests that are made to it. The claims in the JWT are used to determine what properties the user has access to. 294 | 295 | Create the secure `system` service. 296 | 297 | [role="code_command hotspot file=0", subs="quotes"] 298 | ---- 299 | #Create the `SystemResource` class.# 300 | `system/src/main/java/io/openliberty/guides/system/SystemResource.java` 301 | ---- 302 | 303 | // File 0 304 | SystemResource.java 305 | [source, java, linenums, role='code_column hide_tags=copyright'] 306 | ---- 307 | include::finish/system/src/main/java/io/openliberty/guides/system/SystemResource.java[] 308 | ---- 309 | 310 | This class has role-based access control. The role names that are used in the [hotspot=rolesAllowedAdminUser1 hotspot=rolesAllowedAdminUser2 hotspot=rolesAllowedAdmin file=0]`@RolesAllowed` annotations are mapped to group names in the `groups` claim of the JWT, which results in an authorization decision wherever the security constraint is applied. 311 | 312 | The [hotspot=usernameEndpoint file=0]`/username` endpoint returns the system's username and is annotated with the [hotspot=rolesAllowedAdminUser1 file=0]`@RolesAllowed({"admin, "user"})` annotation. Only authenticated users with the role of `admin` or `user` can access this endpoint. 313 | 314 | The [hotspot=osEndpoint file=0]`/os` endpoint returns the system's current OS. Here, the [hotspot=rolesAllowedAdmin file=0]`@RolesAllowed` annotation is limited to `admin`, meaning that only authenticated users with the role of `admin` are able to access the endpoint. 315 | 316 | While the [hotspot=rolesAllowedAdminUser1 hotspot=rolesAllowedAdminUser2 hotspot=rolesAllowedAdmin file=0]`@RolesAllowed` annotation automatically reads from the `groups` claim of the JWT to make an authorization decision, you can also manually access the claims of the JWT by using the [hotspot=claim file=0]`@Claim` annotation. In this case, the `groups` claim is injected into the [hotspot=rolesArray file=0]`roles` JSON array. The roles that are parsed from the `groups` claim of the JWT are then exposed back to the front end at the [hotspot=rolesEndpoint file=0]`/jwtroles` endpoint. To read more about different claims and ways to access them, check out the https://github.com/eclipse/microprofile-jwt-auth/blob/master/spec/src/main/asciidoc/interoperability.asciidoc[MicroProfile JWT documentation^]. 317 | 318 | // ================================================================================================= 319 | // Creating a client to access the secure system service 320 | // ================================================================================================= 321 | 322 | == Creating a client to access the secure system service 323 | 324 | Create a RESTful client interface for the `frontend` service. 325 | 326 | [role="code_command hotspot file=0", subs="quotes"] 327 | ---- 328 | #Create the `SystemClient` class.# 329 | `frontend/src/main/java/io/openliberty/guides/frontend/client/SystemClient.java` 330 | ---- 331 | 332 | // File 0 333 | SystemClient.java 334 | [source, java, linenums, role='code_column hide_tags=copyright'] 335 | ---- 336 | include::finish/frontend/src/main/java/io/openliberty/guides/frontend/client/SystemClient.java[] 337 | ---- 338 | 339 | This interface declares methods for accessing each of the endpoints that were 340 | previously set up in the `system` service. 341 | 342 | The MicroProfile Rest Client feature automatically builds and generates a client implementation based on what is defined in the [hotspot=systemClient file=0]`SystemClient` interface. You don't need to set up the client and connect with the remote service. 343 | 344 | As discussed, the `system` service is secured and requests made to it must include a valid JWT in the `Authorization` header. The [hotspot=headerParam1 hotspot=headerParam2 hotspot=headerParam3 file=0]`@HeaderParam` annotations include the JWT by specifying that the value of the `String authHeader` parameter, which contains the JWT, be used as the value for the `Authorization` header. This header is included in all of the requests that are made to the `system` service through this client. 345 | 346 | Create the application bean that the front-end UI uses to request data. 347 | 348 | [role="code_command hotspot file=1", subs="quotes"] 349 | ---- 350 | #Create the `ApplicationBean` class.# 351 | `frontend/src/main/java/io/openliberty/guides/frontend/ApplicationBean.java` 352 | ---- 353 | 354 | // File 1 355 | ApplicationBean.java 356 | [source, java, linenums, role='code_column hide_tags=copyright'] 357 | ---- 358 | include::finish/frontend/src/main/java/io/openliberty/guides/frontend/ApplicationBean.java[] 359 | ---- 360 | 361 | The application bean is used to populate the table in the front end by making requests for data through the [hotspot=restClient file=1]`defaultRestClient`, which is an injected instance of the [hotspot=systemClient file=0]`SystemClient` class that you created. The [hotspot=getOs file=1]`getOs()`, [hotspot=getUsername file=1]`getUsername()`, and [hotspot=getJwtRoles file=1]`getJwtRoles()` methods call their associated methods of the `SystemClient` class with the [hotspot=authHeader1 hotspot=authHeader2 hotspot=authHeader3 file=1]`authHeader` passed in as a parameter. The `authHeader` is a string that consists of the JWT with `Bearer` prefixed to it. The `authHeader` is included in the `Authorization` header of the subsequent requests that are made by the `defaultRestClient` instance. 362 | 363 | // File 2 364 | LoginBean.java 365 | [source, java, linenums, role='code_column hide_tags=copyright'] 366 | ---- 367 | include::finish/frontend/src/main/java/io/openliberty/guides/frontend/LoginBean.java[] 368 | ---- 369 | 370 | The JWT for these requests is retrieved from the session attributes with the [hotspot=getJwt file=1]`getJwt()` method. The JWT is stored in the session attributes by the provided [hotspot file=2]`LoginBean` class. When the user logs in to the front end, the [hotspot=doLogin file=2]`doLogin()` method is called and builds the JWT. Then, the [hotspot=setAttribute file=2]`setAttribute()` method stores it as an `HttpSession` attribute. The JWT is built by using the [hotspot=jwtBuilder file=2]`JwtBuilder` APIs in the [hotspot=buildJwt file=2]`buildJwt()` method. You can see that the [hotspot=claim file=2]`claim()` method is being used to set the `groups` and the `aud` claims of the token. The `groups` claim is used to provide the role-based access that you implemented. The `aud` claim is used to specify the audience that the JWT is intended for. 371 | // ================================================================================================= 372 | // Configuring MicroProfile JWT 373 | // ================================================================================================= 374 | 375 | == Configuring MicroProfile JWT 376 | 377 | Configure the `mpJwt` feature in the `microprofile-config.properties` file for the `system` service. 378 | 379 | [role="code_command hotspot file=0", subs="quotes"] 380 | ---- 381 | #Create the microprofile-config.properties file.# 382 | `system/src/main/resources/META-INF/microprofile-config.properties` 383 | ---- 384 | 385 | // File 0 386 | microprofile-config.properties 387 | [source, text, linenums, role="code_column hide_tags=propagateHeaders"] 388 | ---- 389 | include::finish/system/src/main/resources/META-INF/microprofile-config.properties[] 390 | ---- 391 | 392 | The following table breaks down some of the properties: 393 | 394 | [cols="<30%,<70%", options="header"] 395 | |=== 396 | | *Property* | *Description* 397 | | [hotspot=issuer file=0]`mp.jwt.verify.issuer` | Specifies the expected value of the issuer claim on an incoming JWT. Incoming JWTs with an issuer claim that's different from this expected value aren't considered valid. 398 | | [hotspot=header file=0]`mp.jwt.token.header` | With this property, you can control the HTTP request header, which is expected to contain a JWT. You can either specify Authorization, by default, or the Cookie values. 399 | | [hotspot=cookie file=0]`mp.jwt.token.cookie` | Specifies the name of the cookie, which is expected to contain a JWT token. The default value is Bearer. 400 | | [hotspot=audiences file=0]`mp.jwt.verify.audiences` | With this property, you can create a list of allowable audience (aud) values. At least one of these values must be found in the claim. Previously, this configuration was included in the `server.xml` file. 401 | | [hotspot=location file=0]`mp.jwt.decrypt.key.location` | With this property, you can specify the location of the Key Management key. It is a Private key that is used to decrypt the Content Encryption key, which is then used to decrypt the JWE ciphertext. This private key must correspond to the public key that is used to encrypt the Content Encryption key. 402 | | [hotspot=algorithm file=0]`mp.jwt.verify.publickey.algorithm` | With this property, you can control the Public Key Signature Algorithm that is supported by the MicroProfile JWT endpoint. The default value is RS256. Previously, this configuration was included in the `server.xml` file. 403 | |=== 404 | 405 | For more information about these and other JWT properties, see the https://openliberty.io/docs/latest/reference/microprofile-config-properties.html#jwt[MicroProfile Config properties for MicroProfile JSON Web Token documentation^]. 406 | 407 | Next, add the MicroProfile JSON Web Token feature to the Liberty `server.xml` configuration file for the `system` service. 408 | 409 | [role="code_command hotspot file=1", subs="quotes"] 410 | ---- 411 | #Replace the system `server.xml` configuration file.# 412 | `system/src/main/liberty/config/server.xml` 413 | ---- 414 | 415 | // File 1 416 | server.xml 417 | [source, xml, linenums, role='code_column hide_tags=copyright'] 418 | ---- 419 | include::finish/system/src/main/liberty/config/server.xml[] 420 | ---- 421 | 422 | The [hotspot=mpJwt file=1]`mpJwt` feature adds the libraries that are required for MicroProfile JWT implementation. 423 | 424 | // ================================================================================================= 425 | // Building and running the application 426 | // ================================================================================================= 427 | 428 | == Building and running the application 429 | 430 | Because you are running the `frontend` and `system` services in dev mode, the changes that you made were automatically picked up. You're now ready to check out your application in your browser. 431 | 432 | // static guide instructions: 433 | ifndef::cloud-hosted[] 434 | In your browser, go to the front-end web application endpoint at http://localhost:9090/login.jsf. Log in with one of the following usernames and its corresponding password: 435 | endif::[] 436 | 437 | // cloud-hosted guide instructions: 438 | ifdef::cloud-hosted[] 439 | To launch the front-end web application, click the following button: 440 | ::startApplication{port="9090" display="external" name="Launch Application" route="/login.jsf"} 441 | 442 | Log in with one of the following usernames and its corresponding password: 443 | endif::[] 444 | 445 | [cols="<35, ^200, ^200"] 446 | |=== 447 | | *Username* | *Password* | *Role* 448 | | bob | bobpwd | admin, user 449 | | alice | alicepwd | user 450 | | carl | carlpwd | user 451 | |=== 452 | 453 | After you log in as an `admin`, you can see the information that's retrieved from the `system` service. Click `Log Out` and log in as a `user`. With successfully implemented role-based access in the application, if you log in as a `user` role, you don't have access to the OS property. 454 | 455 | You can also see the value of the `groups` claim in the row with the `Roles:` label. These roles are read from the JWT and sent back to the front end to be displayed. 456 | 457 | // static guide instructions: 458 | ifndef::cloud-hosted[] 459 | You can check that the `system` service is secured against unauthenticated requests by going to the https://localhost:8443/system/properties/os[https://localhost:8443/system/properties/os^] `system` endpoint in your browser. 460 | endif::[] 461 | 462 | // cloud-hosted guide instructions: 463 | ifdef::cloud-hosted[] 464 | You can check that the ***system*** service is secured against unauthenticated requests by going to the **system** endpoint. Run the following curl command from the terminal in the IDE: 465 | ```bash 466 | curl -k https://localhost:8443/system/properties/os 467 | ``` 468 | 469 | You'll see an empty response because you didn't authenticate with a valid JWT. 470 | endif::[] 471 | 472 | In the front end, you see your JWT displayed in the row with the `JSON Web Token` label. 473 | 474 | To see the specific information that this JWT holds, you can enter it into the token reader on the https://JWT.io[JWT.io website^]. The token reader shows you the header, which contains information about the JWT, as shown in the following example: 475 | 476 | [source, role="no_copy"] 477 | ---- 478 | { 479 | "kid": "NPzyG3ZMzljUwQgbzi44", 480 | "typ": "JWT", 481 | "alg": "RS256" 482 | } 483 | ---- 484 | 485 | The token reader also shows you the payload, which contains the claims information: 486 | 487 | [source, role="no_copy"] 488 | ---- 489 | { 490 | "token_type": "Bearer", 491 | "sub": "bob", 492 | "upn": "bob", 493 | "groups": [ "admin", "user" ], 494 | "iss": "http://openliberty.io", 495 | "exp": 1596723489, 496 | "iat": 1596637089 497 | } 498 | ---- 499 | 500 | You can learn more about these claims in the https://github.com/eclipse/microprofile-jwt-auth/blob/master/spec/src/main/asciidoc/interoperability.asciidoc[MicroProfile JWT documentation^]. 501 | 502 | // ================================================================================================= 503 | // Testing the application 504 | // ================================================================================================= 505 | 506 | == Testing the application 507 | 508 | You can manually check that the `system` service is secure by making requests to each of the endpoints with and without valid JWTs. However, automated tests are a much better approach because they are more reliable and trigger a failure if a breaking change is introduced. 509 | 510 | [role="code_command hotspot file=0", subs="quotes"] 511 | ---- 512 | #Create the `SystemEndpointIT` class.# 513 | `system/src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java` 514 | ---- 515 | 516 | // File 0 517 | SystemEndpointIT.java 518 | [source, java, linenums, role='code_column hide_tags=copyright'] 519 | ---- 520 | include::finish/system/src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java[] 521 | ---- 522 | 523 | The [hotspot=os file=0]`testOSEndpoint()`, [hotspot=username file=0]`testUsernameEndpoint()`, and [hotspot=roles file=0]`testRolesEndpoint()` tests test the `/os`, `/username`, and `/roles` endpoints. 524 | 525 | Each test makes three requests to its associated endpoint. The first [hotspot=adminRequest1 hotspot=adminRequest2 hotspot=adminRequest3 file=0]`makeRequest()` call has a JWT with the `admin` role. The second [hotspot=userRequest1 hotspot=userRequest2 hotspot=userRequest3 file=0]`makeRequest()` call has a JWT with the `user` role. The third [hotspot=nojwtRequest1 hotspot=nojwtRequest2 hotspot=nojwtRequest3 file=0]`makeRequest()` call has no JWT at all. The responses to these requests are checked based on the role-based access rules for the endpoints. The `admin` requests should be successful on all endpoints. The `user` requests should be denied by the `/os` endpoint but successfully access the `/username` and `/jwtroles` endpoints. The requests that don't include a JWT should be denied access to all endpoints. 526 | 527 | === Running the tests 528 | 529 | Because you started Open Liberty in dev mode, press the `enter/return` key from the command-line session of the `system` service to run the tests. You see the following output: 530 | 531 | [source, role="no_copy"] 532 | ---- 533 | ------------------------------------------------------- 534 | T E S T S 535 | ------------------------------------------------------- 536 | Running it.io.openliberty.guides.system.SystemEndpointIT 537 | [ERROR ] CWWKS5522E: The MicroProfile JWT feature cannot perform authentication because a MicroProfile JWT cannot be found in the request. 538 | [ERROR ] CWWKS5522E: The MicroProfile JWT feature cannot perform authentication because a MicroProfile JWT cannot be found in the request. 539 | [ERROR ] CWWKS5522E: The MicroProfile JWT feature cannot perform authentication because a MicroProfile JWT cannot be found in the request. 540 | Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.648 s - in it.io.openliberty.guides.system.SystemEndpointIT 541 | 542 | Results: 543 | 544 | Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 545 | ---- 546 | 547 | The three errors in the output are expected and result from the `system` service successfully rejecting the requests that didn't include a JWT. 548 | 549 | When you are finished testing the application, stop both the `frontend` and `system` services by pressing `CTRL+C` in the command-line sessions where you ran them. 550 | 551 | // ================================================================================================= 552 | // Great work! You're done! 553 | // ================================================================================================= 554 | 555 | == Great work! You're done! 556 | 557 | You learned how to use MicroProfile JWT to validate JWTs, authenticate and authorize users to secure your microservices in Open Liberty. 558 | 559 | include::{common-includes}/attribution.adoc[subs="attributes"] 560 | -------------------------------------------------------------------------------- /assets/JWT_Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/assets/JWT_Diagram.png -------------------------------------------------------------------------------- /finish/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/finish/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /finish/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar 3 | -------------------------------------------------------------------------------- /finish/frontend/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.openliberty.guides 6 | frontend 7 | 1.0-SNAPSHOT 8 | war 9 | 10 | 11 | UTF-8 12 | UTF-8 13 | 11 14 | 11 15 | 9090 16 | 9091 17 | 18 | 19 | 20 | 21 | jakarta.platform 22 | jakarta.jakartaee-api 23 | 10.0.0 24 | provided 25 | 26 | 27 | org.eclipse.microprofile 28 | microprofile 29 | 7.0 30 | pom 31 | provided 32 | 33 | 34 | com.ibm.websphere.appserver.api 35 | com.ibm.websphere.appserver.api.jwt 36 | 1.1.101 37 | provided 38 | 39 | 40 | 41 | 42 | ${project.artifactId} 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-war-plugin 47 | 3.4.0 48 | 49 | 50 | io.openliberty.tools 51 | liberty-maven-plugin 52 | 3.11.3 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /finish/frontend/src/main/java/io/openliberty/guides/frontend/ApplicationBean.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend; 13 | 14 | import jakarta.enterprise.context.ApplicationScoped; 15 | import jakarta.inject.Inject; 16 | import jakarta.inject.Named; 17 | 18 | import org.eclipse.microprofile.rest.client.inject.RestClient; 19 | 20 | import io.openliberty.guides.frontend.client.SystemClient; 21 | import io.openliberty.guides.frontend.util.SessionUtils; 22 | 23 | 24 | @ApplicationScoped 25 | @Named 26 | public class ApplicationBean { 27 | 28 | // tag::restClient[] 29 | @Inject 30 | @RestClient 31 | private SystemClient defaultRestClient; 32 | // end::restClient[] 33 | 34 | // tag::getJwt[] 35 | public String getJwt() { 36 | String jwtTokenString = SessionUtils.getJwtToken(); 37 | String authHeader = "Bearer " + jwtTokenString; 38 | return authHeader; 39 | } 40 | // end::getJwt[] 41 | 42 | // tag::getOs[] 43 | public String getOs() { 44 | String authHeader = getJwt(); 45 | String os; 46 | try { 47 | // tag::authHeader1[] 48 | os = defaultRestClient.getOS(authHeader); 49 | // end::authHeader1[] 50 | } catch (Exception e) { 51 | return "You are not authorized to access this system property"; 52 | } 53 | return os; 54 | } 55 | // end::getOs[] 56 | 57 | // tag::getUsername[] 58 | public String getUsername() { 59 | String authHeader = getJwt(); 60 | // tag::authHeader2[] 61 | return defaultRestClient.getUsername(authHeader); 62 | // end::authHeader2[] 63 | } 64 | // end::getUsername[] 65 | 66 | // tag::getJwtRoles[] 67 | public String getJwtRoles() { 68 | String authHeader = getJwt(); 69 | // tag::authHeader3[] 70 | return defaultRestClient.getJwtRoles(authHeader); 71 | // end::authHeader3[] 72 | } 73 | // end::getJwtRoles[] 74 | 75 | } 76 | -------------------------------------------------------------------------------- /finish/frontend/src/main/java/io/openliberty/guides/frontend/LoginBean.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2018, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend; 13 | 14 | import java.util.Set; 15 | import java.util.HashSet; 16 | import jakarta.servlet.ServletException; 17 | import jakarta.servlet.http.HttpServletRequest; 18 | import jakarta.servlet.http.HttpSession; 19 | import jakarta.enterprise.context.ApplicationScoped; 20 | import jakarta.inject.Named; 21 | 22 | import com.ibm.websphere.security.jwt.JwtBuilder; 23 | import com.ibm.websphere.security.jwt.Claims; 24 | 25 | import io.openliberty.guides.frontend.util.SessionUtils; 26 | 27 | // tag::loginBean[] 28 | @ApplicationScoped 29 | @Named 30 | public class LoginBean { 31 | 32 | private String username; 33 | private String password; 34 | 35 | public void setUsername(String username) { 36 | this.username = username; 37 | } 38 | 39 | public void setPassword(String password) { 40 | this.password = password; 41 | } 42 | 43 | public String getUsername() { 44 | return username; 45 | } 46 | 47 | public String getPassword() { 48 | return password; 49 | } 50 | 51 | // tag::doLogin[] 52 | public String doLogin() throws Exception { 53 | HttpServletRequest request = SessionUtils.getRequest(); 54 | 55 | try { 56 | request.logout(); 57 | request.login(this.username, this.password); 58 | } catch (ServletException e) { 59 | System.out.println("Login failed."); 60 | return "error.jsf"; 61 | } 62 | 63 | String remoteUser = request.getRemoteUser(); 64 | Set roles = getRoles(request); 65 | if (remoteUser != null && remoteUser.equals(username)) { 66 | String jwt = buildJwt(username, roles); 67 | HttpSession ses = request.getSession(); 68 | if (ses == null) { 69 | System.out.println("Session timed out."); 70 | } else { 71 | // tag::setAttribute[] 72 | ses.setAttribute("jwt", jwt); 73 | // end::setAttribute[] 74 | } 75 | } else { 76 | System.out.println("Failed to update JWT in session."); 77 | } 78 | return "application.jsf?faces-redirect=true"; 79 | } 80 | // end::doLogin[] 81 | // tag::buildJwt[] 82 | 83 | private String buildJwt(String userName, Set roles) throws Exception { 84 | // tag::jwtBuilder[] 85 | return JwtBuilder.create("jwtFrontEndBuilder") 86 | // end::jwtBuilder[] 87 | .claim(Claims.SUBJECT, userName) 88 | .claim("upn", userName) 89 | // tag::claim[] 90 | .claim("groups", roles.toArray(new String[roles.size()])) 91 | .claim("aud", "systemService") 92 | // end::claim[] 93 | .buildJwt() 94 | .compact(); 95 | 96 | } 97 | // end::buildJwt[] 98 | 99 | private Set getRoles(HttpServletRequest request) { 100 | Set roles = new HashSet(); 101 | boolean isAdmin = request.isUserInRole("admin"); 102 | boolean isUser = request.isUserInRole("user"); 103 | if (isAdmin) { 104 | roles.add("admin"); 105 | } 106 | if (isUser) { 107 | roles.add("user"); 108 | } 109 | return roles; 110 | } 111 | } 112 | // end::loginBean[] 113 | -------------------------------------------------------------------------------- /finish/frontend/src/main/java/io/openliberty/guides/frontend/client/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/finish/frontend/src/main/java/io/openliberty/guides/frontend/client/.gitkeep -------------------------------------------------------------------------------- /finish/frontend/src/main/java/io/openliberty/guides/frontend/client/SystemClient.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend.client; 13 | 14 | import jakarta.enterprise.context.RequestScoped; 15 | import jakarta.ws.rs.GET; 16 | import jakarta.ws.rs.Path; 17 | import jakarta.ws.rs.Produces; 18 | import jakarta.ws.rs.core.MediaType; 19 | import jakarta.ws.rs.HeaderParam; 20 | 21 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; 22 | 23 | // tag::systemClient[] 24 | @RegisterRestClient(baseUri = "https://localhost:8443/system") 25 | @Path("/properties") 26 | @RequestScoped 27 | public interface SystemClient extends AutoCloseable { 28 | 29 | @GET 30 | @Path("/os") 31 | @Produces(MediaType.APPLICATION_JSON) 32 | // tag::headerParam1[] 33 | String getOS(@HeaderParam("Authorization") String authHeader); 34 | // end::headerParam1[] 35 | 36 | @GET 37 | @Path("/username") 38 | @Produces(MediaType.APPLICATION_JSON) 39 | // tag::headerParam2[] 40 | String getUsername(@HeaderParam("Authorization") String authHeader); 41 | // end::headerParam2[] 42 | 43 | @GET 44 | @Path("/jwtroles") 45 | @Produces(MediaType.APPLICATION_JSON) 46 | // tag::headerParam3[] 47 | String getJwtRoles(@HeaderParam("Authorization") String authHeader); 48 | // end::headerParam3[] 49 | } 50 | // end::systemClient[] 51 | -------------------------------------------------------------------------------- /finish/frontend/src/main/java/io/openliberty/guides/frontend/filters/NoCacheFilter.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend.filters; 13 | 14 | import java.io.IOException; 15 | 16 | import jakarta.servlet.Filter; 17 | import jakarta.servlet.FilterChain; 18 | import jakarta.servlet.ServletException; 19 | import jakarta.servlet.ServletRequest; 20 | import jakarta.servlet.ServletResponse; 21 | import jakarta.servlet.annotation.WebFilter; 22 | import jakarta.servlet.http.HttpServletResponse; 23 | 24 | @WebFilter(servletNames = { "Faces Servlet" }) 25 | public class NoCacheFilter implements Filter { 26 | 27 | @Override 28 | public void doFilter(ServletRequest request, 29 | ServletResponse response, FilterChain chain) 30 | throws IOException, ServletException { 31 | HttpServletResponse httpServletResponse = 32 | (HttpServletResponse) response; 33 | httpServletResponse.setHeader("Cache-Control", 34 | "no-store, no-cache, must-revalidate, max-age=0"); 35 | httpServletResponse.setDateHeader("Expires", 0); 36 | httpServletResponse.setHeader("Pragma", "no-cache"); 37 | chain.doFilter(request, response); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /finish/frontend/src/main/java/io/openliberty/guides/frontend/models/SystemModel.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend.models; 13 | 14 | import jakarta.json.JsonObject; 15 | 16 | public class SystemModel { 17 | private String hostname; 18 | private String username; 19 | private String osName; 20 | 21 | public SystemModel(JsonObject jo) { 22 | hostname = jo.getString("hostname"); 23 | 24 | JsonObject props = jo.getJsonObject("properties"); 25 | username = props.getString("user.name"); 26 | osName = props.getString("os.name"); 27 | } 28 | 29 | public String getHostname() { 30 | return hostname; 31 | } 32 | 33 | public String getUsername() { 34 | return username; 35 | } 36 | 37 | public String getOsName() { 38 | return osName; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /finish/frontend/src/main/java/io/openliberty/guides/frontend/util/SessionUtils.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2018, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | // tag::jwt[] 13 | package io.openliberty.guides.frontend.util; 14 | 15 | import jakarta.faces.context.FacesContext; 16 | import jakarta.servlet.http.HttpServletRequest; 17 | import jakarta.servlet.http.HttpSession; 18 | 19 | public class SessionUtils { 20 | // Gets the current session for a logged in user. 21 | public static HttpSession getSession() { 22 | return (HttpSession) FacesContext.getCurrentInstance().getExternalContext() 23 | .getSession(false); 24 | } 25 | 26 | // Gets Http servlet for user request information. 27 | public static HttpServletRequest getRequest() { 28 | return (HttpServletRequest) FacesContext.getCurrentInstance() 29 | .getExternalContext().getRequest(); 30 | } 31 | 32 | public static String getJwtToken() { 33 | return (String) getSession().getAttribute("jwt"); 34 | } 35 | 36 | } 37 | // end::jwt[] 38 | -------------------------------------------------------------------------------- /finish/frontend/src/main/liberty/config/resources/security/key.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/finish/frontend/src/main/liberty/config/resources/security/key.p12 -------------------------------------------------------------------------------- /finish/frontend/src/main/liberty/config/server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jakartaee-10.0 6 | microprofile-7.0 7 | restfulWS 8 | jsonb 9 | jsonp 10 | faces 11 | cdi 12 | 13 | appSecurity 14 | servlet 15 | mpJwt 16 | mpConfig 17 | mpRestClient 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /finish/frontend/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Liberty Project 6 | 7 | 10 | 11 | org.apache.myfaces.SECRET 12 | c3R1ZmZhbmQ= 13 | 14 | 15 | 16 | org.apache.myfaces.MAC_SECRET 17 | bW9yZXN0dWY= 18 | 19 | 20 | 21 | org.apache.myfaces.SERIALIZE_STATE_IN_SESSION 22 | false 23 | 24 | 25 | 40 | 41 | 42 | Faces Servlet 43 | jakarta.faces.webapp.FacesServlet 44 | 1 45 | 46 | 47 | 48 | 49 | Faces Servlet 50 | *.jsf 51 | 52 | 53 | 54 | index.jsf 55 | 56 | 57 | 58 | 59 | 60 | admin 61 | 62 | 63 | 64 | user 65 | 66 | 67 | 68 | 69 | 70 | 71 | ViewProperties 72 | /application.jsf 73 | GET 74 | 75 | 76 | user 77 | 78 | 79 | 80 | 81 | FORM 82 | WebRealm 83 | 84 | /login.jsf 85 | /error.jsf 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /finish/frontend/src/main/webapp/application.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 23 | 24 | Application 25 | 62 | 63 | 64 | 65 |
66 | 67 | 68 |
69 |
70 | 71 | 72 | System Username: 73 | #{applicationBean.username} 74 | Current OS: 75 | #{applicationBean.os} 76 | Roles: 77 | #{applicationBean.jwtRoles} 78 | JSON Web Token: 79 | #{applicationBean.jwt} 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /finish/frontend/src/main/webapp/error.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 23 | Security Login Error 24 | 25 | 26 |

A form login authentication failure occurred!

27 |

28 | The user name or password might be incorrect, or the user might not exist. 29 |

30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /finish/frontend/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/finish/frontend/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /finish/frontend/src/main/webapp/index.xhtml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 |

Welcome to your Open Liberty application

16 |

Open Liberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. Find out more at openliberty.io.

17 |

Log in to try out the application.

18 |
19 |

Eclipse MicroProfile

20 |

21 | The Eclipse MicroProfile project is an open community with the aim of optimizing enterprise Java for a microservices architecture. 22 | MicroProfile evolves with guidance from the community. 23 |

24 |

25 | If you want to share your thoughts, you can post straight to the 26 | MicroProfile Google group. 27 |

28 |

29 | For more information about the features used in this application, see the Open Liberty documentation: 30 |

43 |

44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /finish/frontend/src/main/webapp/login.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 23 | Security Login Page 24 | 25 |

Form Login

26 | 27 |

28 | Username 29 | 30 |

31 |

32 | Password 33 | 34 |

35 |

36 | 38 | 39 |

41 |

42 |
43 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /finish/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Apache Maven Wrapper startup batch script, version 3.3.2 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | # e.g. to debug Maven itself, use 32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | # ---------------------------------------------------------------------------- 35 | 36 | if [ -z "$MAVEN_SKIP_RC" ]; then 37 | 38 | if [ -f /usr/local/etc/mavenrc ]; then 39 | . /usr/local/etc/mavenrc 40 | fi 41 | 42 | if [ -f /etc/mavenrc ]; then 43 | . /etc/mavenrc 44 | fi 45 | 46 | if [ -f "$HOME/.mavenrc" ]; then 47 | . "$HOME/.mavenrc" 48 | fi 49 | 50 | fi 51 | 52 | # OS specific support. $var _must_ be set to either true or false. 53 | cygwin=false 54 | darwin=false 55 | mingw=false 56 | case "$(uname)" in 57 | CYGWIN*) cygwin=true ;; 58 | MINGW*) mingw=true ;; 59 | Darwin*) 60 | darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | JAVA_HOME="$(/usr/libexec/java_home)" 66 | export JAVA_HOME 67 | else 68 | JAVA_HOME="/Library/Java/Home" 69 | export JAVA_HOME 70 | fi 71 | fi 72 | ;; 73 | esac 74 | 75 | if [ -z "$JAVA_HOME" ]; then 76 | if [ -r /etc/gentoo-release ]; then 77 | JAVA_HOME=$(java-config --jre-home) 78 | fi 79 | fi 80 | 81 | # For Cygwin, ensure paths are in UNIX format before anything is touched 82 | if $cygwin; then 83 | [ -n "$JAVA_HOME" ] \ 84 | && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 85 | [ -n "$CLASSPATH" ] \ 86 | && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 87 | fi 88 | 89 | # For Mingw, ensure paths are in UNIX format before anything is touched 90 | if $mingw; then 91 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ 92 | && JAVA_HOME="$( 93 | cd "$JAVA_HOME" || ( 94 | echo "cannot cd into $JAVA_HOME." >&2 95 | exit 1 96 | ) 97 | pwd 98 | )" 99 | fi 100 | 101 | if [ -z "$JAVA_HOME" ]; then 102 | javaExecutable="$(which javac)" 103 | if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then 104 | # readlink(1) is not available as standard on Solaris 10. 105 | readLink=$(which readlink) 106 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then 107 | if $darwin; then 108 | javaHome="$(dirname "$javaExecutable")" 109 | javaExecutable="$(cd "$javaHome" && pwd -P)/javac" 110 | else 111 | javaExecutable="$(readlink -f "$javaExecutable")" 112 | fi 113 | javaHome="$(dirname "$javaExecutable")" 114 | javaHome=$(expr "$javaHome" : '\(.*\)/bin') 115 | JAVA_HOME="$javaHome" 116 | export JAVA_HOME 117 | fi 118 | fi 119 | fi 120 | 121 | if [ -z "$JAVACMD" ]; then 122 | if [ -n "$JAVA_HOME" ]; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ]; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD="$JAVA_HOME/jre/sh/java" 126 | else 127 | JAVACMD="$JAVA_HOME/bin/java" 128 | fi 129 | else 130 | JAVACMD="$( 131 | \unset -f command 2>/dev/null 132 | \command -v java 133 | )" 134 | fi 135 | fi 136 | 137 | if [ ! -x "$JAVACMD" ]; then 138 | echo "Error: JAVA_HOME is not defined correctly." >&2 139 | echo " We cannot execute $JAVACMD" >&2 140 | exit 1 141 | fi 142 | 143 | if [ -z "$JAVA_HOME" ]; then 144 | echo "Warning: JAVA_HOME environment variable is not set." >&2 145 | fi 146 | 147 | # traverses directory structure from process work directory to filesystem root 148 | # first directory with .mvn subdirectory is considered project base directory 149 | find_maven_basedir() { 150 | if [ -z "$1" ]; then 151 | echo "Path not specified to find_maven_basedir" >&2 152 | return 1 153 | fi 154 | 155 | basedir="$1" 156 | wdir="$1" 157 | while [ "$wdir" != '/' ]; do 158 | if [ -d "$wdir"/.mvn ]; then 159 | basedir=$wdir 160 | break 161 | fi 162 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 163 | if [ -d "${wdir}" ]; then 164 | wdir=$( 165 | cd "$wdir/.." || exit 1 166 | pwd 167 | ) 168 | fi 169 | # end of workaround 170 | done 171 | printf '%s' "$( 172 | cd "$basedir" || exit 1 173 | pwd 174 | )" 175 | } 176 | 177 | # concatenates all lines of a file 178 | concat_lines() { 179 | if [ -f "$1" ]; then 180 | # Remove \r in case we run on Windows within Git Bash 181 | # and check out the repository with auto CRLF management 182 | # enabled. Otherwise, we may read lines that are delimited with 183 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word 184 | # splitting rules. 185 | tr -s '\r\n' ' ' <"$1" 186 | fi 187 | } 188 | 189 | log() { 190 | if [ "$MVNW_VERBOSE" = true ]; then 191 | printf '%s\n' "$1" 192 | fi 193 | } 194 | 195 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")") 196 | if [ -z "$BASE_DIR" ]; then 197 | exit 1 198 | fi 199 | 200 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 201 | export MAVEN_PROJECTBASEDIR 202 | log "$MAVEN_PROJECTBASEDIR" 203 | 204 | ########################################################################################## 205 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 206 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 207 | ########################################################################################## 208 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" 209 | if [ -r "$wrapperJarPath" ]; then 210 | log "Found $wrapperJarPath" 211 | else 212 | log "Couldn't find $wrapperJarPath, downloading it ..." 213 | 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 216 | else 217 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 218 | fi 219 | while IFS="=" read -r key value; do 220 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) 221 | safeValue=$(echo "$value" | tr -d '\r') 222 | case "$key" in wrapperUrl) 223 | wrapperUrl="$safeValue" 224 | break 225 | ;; 226 | esac 227 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 228 | log "Downloading from: $wrapperUrl" 229 | 230 | if $cygwin; then 231 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 232 | fi 233 | 234 | if command -v wget >/dev/null; then 235 | log "Found wget ... using wget" 236 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" 237 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 238 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 239 | else 240 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | fi 242 | elif command -v curl >/dev/null; then 243 | log "Found curl ... using curl" 244 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" 245 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 246 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 247 | else 248 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 249 | fi 250 | else 251 | log "Falling back to using Java to download" 252 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" 253 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" 254 | # For Cygwin, switch paths to Windows format before running javac 255 | if $cygwin; then 256 | javaSource=$(cygpath --path --windows "$javaSource") 257 | javaClass=$(cygpath --path --windows "$javaClass") 258 | fi 259 | if [ -e "$javaSource" ]; then 260 | if [ ! -e "$javaClass" ]; then 261 | log " - Compiling MavenWrapperDownloader.java ..." 262 | ("$JAVA_HOME/bin/javac" "$javaSource") 263 | fi 264 | if [ -e "$javaClass" ]; then 265 | log " - Running MavenWrapperDownloader.java ..." 266 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" 267 | fi 268 | fi 269 | fi 270 | fi 271 | ########################################################################################## 272 | # End of extension 273 | ########################################################################################## 274 | 275 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file 276 | wrapperSha256Sum="" 277 | while IFS="=" read -r key value; do 278 | case "$key" in wrapperSha256Sum) 279 | wrapperSha256Sum=$value 280 | break 281 | ;; 282 | esac 283 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 284 | if [ -n "$wrapperSha256Sum" ]; then 285 | wrapperSha256Result=false 286 | if command -v sha256sum >/dev/null; then 287 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then 288 | wrapperSha256Result=true 289 | fi 290 | elif command -v shasum >/dev/null; then 291 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then 292 | wrapperSha256Result=true 293 | fi 294 | else 295 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 296 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 297 | exit 1 298 | fi 299 | if [ $wrapperSha256Result = false ]; then 300 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 301 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 302 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 303 | exit 1 304 | fi 305 | fi 306 | 307 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 308 | 309 | # For Cygwin, switch paths to Windows format before running java 310 | if $cygwin; then 311 | [ -n "$JAVA_HOME" ] \ 312 | && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 313 | [ -n "$CLASSPATH" ] \ 314 | && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 315 | [ -n "$MAVEN_PROJECTBASEDIR" ] \ 316 | && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 317 | fi 318 | 319 | # Provide a "standardized" way to retrieve the CLI args that will 320 | # work with both Windows and non-Windows executions. 321 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" 322 | export MAVEN_CMD_LINE_ARGS 323 | 324 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 325 | 326 | # shellcheck disable=SC2086 # safe args 327 | exec "$JAVACMD" \ 328 | $MAVEN_OPTS \ 329 | $MAVEN_DEBUG_OPTS \ 330 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 331 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 332 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 333 | -------------------------------------------------------------------------------- /finish/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Apache Maven Wrapper startup batch script, version 3.3.2 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 30 | @REM e.g. to debug Maven itself, use 31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 33 | @REM ---------------------------------------------------------------------------- 34 | 35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 36 | @echo off 37 | @REM set title of command window 38 | title %0 39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 41 | 42 | @REM set %HOME% to equivalent of $HOME 43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 44 | 45 | @REM Execute a user defined script before this one 46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 50 | :skipRcPre 51 | 52 | @setlocal 53 | 54 | set ERROR_CODE=0 55 | 56 | @REM To isolate internal variables from possible post scripts, we use another setlocal 57 | @setlocal 58 | 59 | @REM ==== START VALIDATION ==== 60 | if not "%JAVA_HOME%" == "" goto OkJHome 61 | 62 | echo. >&2 63 | echo Error: JAVA_HOME not found in your environment. >&2 64 | echo Please set the JAVA_HOME variable in your environment to match the >&2 65 | echo location of your Java installation. >&2 66 | echo. >&2 67 | goto error 68 | 69 | :OkJHome 70 | if exist "%JAVA_HOME%\bin\java.exe" goto init 71 | 72 | echo. >&2 73 | echo Error: JAVA_HOME is set to an invalid directory. >&2 74 | echo JAVA_HOME = "%JAVA_HOME%" >&2 75 | echo Please set the JAVA_HOME variable in your environment to match the >&2 76 | echo location of your Java installation. >&2 77 | echo. >&2 78 | goto error 79 | 80 | @REM ==== END VALIDATION ==== 81 | 82 | :init 83 | 84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 85 | @REM Fallback to current working directory if not found. 86 | 87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 89 | 90 | set EXEC_DIR=%CD% 91 | set WDIR=%EXEC_DIR% 92 | :findBaseDir 93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 94 | cd .. 95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 96 | set WDIR=%CD% 97 | goto findBaseDir 98 | 99 | :baseDirFound 100 | set MAVEN_PROJECTBASEDIR=%WDIR% 101 | cd "%EXEC_DIR%" 102 | goto endDetectBaseDir 103 | 104 | :baseDirNotFound 105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 106 | cd "%EXEC_DIR%" 107 | 108 | :endDetectBaseDir 109 | 110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 111 | 112 | @setlocal EnableExtensions EnableDelayedExpansion 113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 115 | 116 | :endReadAdditionalConfig 117 | 118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 123 | 124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | if "%MVNW_VERBOSE%" == "true" ( 132 | echo Found %WRAPPER_JAR% 133 | ) 134 | ) else ( 135 | if not "%MVNW_REPOURL%" == "" ( 136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 137 | ) 138 | if "%MVNW_VERBOSE%" == "true" ( 139 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 140 | echo Downloading from: %WRAPPER_URL% 141 | ) 142 | 143 | powershell -Command "&{"^ 144 | "$webclient = new-object System.Net.WebClient;"^ 145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 147 | "}"^ 148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ 149 | "}" 150 | if "%MVNW_VERBOSE%" == "true" ( 151 | echo Finished downloading %WRAPPER_JAR% 152 | ) 153 | ) 154 | @REM End of extension 155 | 156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file 157 | SET WRAPPER_SHA_256_SUM="" 158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B 160 | ) 161 | IF NOT %WRAPPER_SHA_256_SUM%=="" ( 162 | powershell -Command "&{"^ 163 | "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ 164 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ 165 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ 166 | " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ 167 | " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ 168 | " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ 169 | " exit 1;"^ 170 | "}"^ 171 | "}" 172 | if ERRORLEVEL 1 goto error 173 | ) 174 | 175 | @REM Provide a "standardized" way to retrieve the CLI args that will 176 | @REM work with both Windows and non-Windows executions. 177 | set MAVEN_CMD_LINE_ARGS=%* 178 | 179 | %MAVEN_JAVA_EXE% ^ 180 | %JVM_CONFIG_MAVEN_PROPS% ^ 181 | %MAVEN_OPTS% ^ 182 | %MAVEN_DEBUG_OPTS% ^ 183 | -classpath %WRAPPER_JAR% ^ 184 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 185 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 186 | if ERRORLEVEL 1 goto error 187 | goto end 188 | 189 | :error 190 | set ERROR_CODE=1 191 | 192 | :end 193 | @endlocal & set ERROR_CODE=%ERROR_CODE% 194 | 195 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 196 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 197 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 198 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 199 | :skipRcPost 200 | 201 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 202 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 203 | 204 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 205 | 206 | cmd /C exit /B %ERROR_CODE% 207 | -------------------------------------------------------------------------------- /finish/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | io.openliberty.guides 9 | guide-microprofile-jwt 10 | 1.0-SNAPSHOT 11 | pom 12 | 13 | 14 | frontend 15 | system 16 | 17 | -------------------------------------------------------------------------------- /finish/system/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | io.openliberty.guides 9 | system 10 | 1.0-SNAPSHOT 11 | war 12 | 13 | 14 | UTF-8 15 | UTF-8 16 | 11 17 | 11 18 | 19 | localhost 20 | 8080 21 | 8443 22 | http://openliberty.io 23 | 24 | 25 | 26 | 27 | 28 | jakarta.platform 29 | jakarta.jakartaee-api 30 | 10.0.0 31 | provided 32 | 33 | 34 | org.eclipse.microprofile 35 | 36 | microprofile 37 | 38 | 7.0 39 | pom 40 | provided 41 | 42 | 43 | 44 | org.apache.commons 45 | commons-lang3 46 | 3.17.0 47 | 48 | 49 | 50 | org.junit.jupiter 51 | junit-jupiter 52 | 5.13.0 53 | test 54 | 55 | 56 | org.jboss.resteasy 57 | resteasy-client 58 | 6.2.12.Final 59 | test 60 | 61 | 62 | org.jboss.resteasy 63 | resteasy-json-binding-provider 64 | 6.2.12.Final 65 | test 66 | 67 | 68 | org.glassfish 69 | jakarta.json 70 | 2.0.1 71 | test 72 | 73 | 74 | io.vertx 75 | vertx-auth-jwt 76 | 5.0.0 77 | test 78 | 79 | 80 | io.netty 81 | netty-resolver-dns-native-macos 82 | 4.1.119.Final 83 | osx-x86_64 84 | test 85 | 86 | 87 | 88 | 89 | ${project.artifactId} 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-war-plugin 94 | 3.4.0 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-surefire-plugin 100 | 3.5.3 101 | 102 | 103 | 104 | io.openliberty.tools 105 | liberty-maven-plugin 106 | 3.11.3 107 | 108 | 109 | 110 | org.apache.maven.plugins 111 | maven-failsafe-plugin 112 | 3.5.3 113 | 114 | 115 | ${liberty.var.default.hostname} 116 | ${liberty.var.http.port} 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /finish/system/src/main/java/io/openliberty/guides/system/SystemApplication.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.system; 13 | 14 | import jakarta.ws.rs.core.Application; 15 | import jakarta.ws.rs.ApplicationPath; 16 | 17 | @ApplicationPath("system") 18 | public class SystemApplication extends Application { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /finish/system/src/main/java/io/openliberty/guides/system/SystemResource.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.system; 13 | 14 | import jakarta.json.JsonArray; 15 | import jakarta.enterprise.context.RequestScoped; 16 | import jakarta.inject.Inject; 17 | import jakarta.ws.rs.GET; 18 | import jakarta.ws.rs.Path; 19 | import jakarta.ws.rs.Produces; 20 | import jakarta.ws.rs.core.MediaType; 21 | import jakarta.annotation.security.RolesAllowed; 22 | 23 | import org.eclipse.microprofile.jwt.Claim; 24 | 25 | @RequestScoped 26 | @Path("/properties") 27 | public class SystemResource { 28 | 29 | @Inject 30 | // tag::claim[] 31 | @Claim("groups") 32 | // end::claim[] 33 | // tag::rolesArray[] 34 | private JsonArray roles; 35 | // end::rolesArray[] 36 | 37 | @GET 38 | // tag::usernameEndpoint[] 39 | @Path("/username") 40 | // end::usernameEndpoint[] 41 | @Produces(MediaType.APPLICATION_JSON) 42 | // tag::rolesAllowedAdminUser1[] 43 | @RolesAllowed({ "admin", "user" }) 44 | // end::rolesAllowedAdminUser1[] 45 | public String getUsername() { 46 | return System.getProperties().getProperty("user.name"); 47 | } 48 | 49 | @GET 50 | // tag::osEndpoint[] 51 | @Path("/os") 52 | // end::osEndpoint[] 53 | @Produces(MediaType.APPLICATION_JSON) 54 | // tag::rolesAllowedAdmin[] 55 | @RolesAllowed({ "admin" }) 56 | // end::rolesAllowedAdmin[] 57 | public String getOS() { 58 | return System.getProperties().getProperty("os.name"); 59 | } 60 | 61 | @GET 62 | // tag::rolesEndpoint[] 63 | @Path("/jwtroles") 64 | // end::rolesEndpoint[] 65 | @Produces(MediaType.APPLICATION_JSON) 66 | // tag::rolesAllowedAdminUser2[] 67 | @RolesAllowed({ "admin", "user" }) 68 | // end::rolesAllowedAdminUser2[] 69 | public String getRoles() { 70 | return roles.toString(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /finish/system/src/main/liberty/config/resources/security/key.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/finish/system/src/main/liberty/config/resources/security/key.p12 -------------------------------------------------------------------------------- /finish/system/src/main/liberty/config/server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jakartaee-10.0 5 | microprofile-7.0 6 | restfulWS 7 | jsonb 8 | jsonp 9 | cdi 10 | mpConfig 11 | mpRestClient 12 | appSecurity 13 | servlet 14 | 15 | mpJwt 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /finish/system/src/main/resources/META-INF/microprofile-config.properties: -------------------------------------------------------------------------------- 1 | # tag::issuer[] 2 | mp.jwt.verify.issuer=http://openliberty.io 3 | # end::issuer[] 4 | # tag::header[] 5 | mp.jwt.token.header=Authorization 6 | # end::header[] 7 | # tag::cookie[] 8 | mp.jwt.token.cookie=Bearer 9 | # end::cookie[] 10 | # tag::audiences[] 11 | mp.jwt.verify.audiences=systemService, adminServices 12 | # end::audiences[] 13 | # tag::location[] 14 | # mp.jwt.decrypt.key.location=privatekey.pem 15 | # end::location[] 16 | # tag::algorithm[] 17 | mp.jwt.verify.publickey.algorithm=RS256 18 | # end::algorithm[] 19 | -------------------------------------------------------------------------------- /finish/system/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Liberty Project 6 | 7 | 8 | index.html 9 | 10 | -------------------------------------------------------------------------------- /finish/system/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/finish/system/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /finish/system/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 |

Welcome to your Open Liberty application

19 |

Open Liberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. Find out more at openliberty.io.

20 |
21 |

Eclipse MicroProfile

22 |

23 | The Eclipse MicroProfile project is an open community with the aim of optimizing enterprise Java for a microservices architecture. 24 | MicroProfile evolves with guidance from the community. 25 |

26 |

27 | If you want to share your thoughts, you can post straight to the 28 | MicroProfile Google group. 29 |

30 |

31 | For more information about the features used in this application, see the Open Liberty documentation: 32 |

44 |

45 |
46 | 47 | -------------------------------------------------------------------------------- /finish/system/src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2023 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package it.io.openliberty.guides.system; 13 | 14 | import jakarta.ws.rs.client.Client; 15 | import jakarta.ws.rs.client.ClientBuilder; 16 | import jakarta.ws.rs.client.Invocation.Builder; 17 | import jakarta.ws.rs.core.Response; 18 | import jakarta.ws.rs.core.HttpHeaders; 19 | import jakarta.ws.rs.core.MediaType; 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.junit.jupiter.api.BeforeAll; 23 | import static org.junit.jupiter.api.Assertions.assertEquals; 24 | 25 | import it.io.openliberty.guides.system.util.JwtBuilder; 26 | 27 | public class SystemEndpointIT { 28 | 29 | static String authHeaderAdmin; 30 | static String authHeaderUser; 31 | static String urlOS; 32 | static String urlUsername; 33 | static String urlRoles; 34 | 35 | @BeforeAll 36 | public static void setup() throws Exception { 37 | String urlBase = "http://" + System.getProperty("hostname") 38 | + ":" + System.getProperty("http.port") 39 | + "/system/properties"; 40 | urlOS = urlBase + "/os"; 41 | urlUsername = urlBase + "/username"; 42 | urlRoles = urlBase + "/jwtroles"; 43 | 44 | authHeaderAdmin = "Bearer " + new JwtBuilder().createAdminJwt("testUser"); 45 | authHeaderUser = "Bearer " + new JwtBuilder().createUserJwt("testUser"); 46 | } 47 | 48 | @Test 49 | // tag::os[] 50 | public void testOSEndpoint() { 51 | // tag::adminRequest1[] 52 | Response response = makeRequest(urlOS, authHeaderAdmin); 53 | // end::adminRequest1[] 54 | assertEquals(200, response.getStatus(), 55 | "Incorrect response code from " + urlOS); 56 | assertEquals(System.getProperty("os.name"), response.readEntity(String.class), 57 | "The system property for the local and remote JVM should match"); 58 | 59 | // tag::userRequest1[] 60 | response = makeRequest(urlOS, authHeaderUser); 61 | // end::userRequest1[] 62 | assertEquals(403, response.getStatus(), 63 | "Incorrect response code from " + urlOS); 64 | 65 | // tag::nojwtRequest1[] 66 | response = makeRequest(urlOS, null); 67 | // end::nojwtRequest1[] 68 | assertEquals(401, response.getStatus(), 69 | "Incorrect response code from " + urlOS); 70 | 71 | response.close(); 72 | } 73 | // end::os[] 74 | 75 | @Test 76 | // tag::username[] 77 | public void testUsernameEndpoint() { 78 | // tag::adminRequest2[] 79 | Response response = makeRequest(urlUsername, authHeaderAdmin); 80 | // end::adminRequest2[] 81 | assertEquals(200, response.getStatus(), 82 | "Incorrect response code from " + urlUsername); 83 | 84 | // tag::userRequest2[] 85 | response = makeRequest(urlUsername, authHeaderUser); 86 | // end::userRequest2[] 87 | assertEquals(200, response.getStatus(), 88 | "Incorrect response code from " + urlUsername); 89 | 90 | // tag::nojwtRequest2[] 91 | response = makeRequest(urlUsername, null); 92 | // end::nojwtRequest2[] 93 | assertEquals(401, response.getStatus(), 94 | "Incorrect response code from " + urlUsername); 95 | 96 | response.close(); 97 | } 98 | // end::username[] 99 | 100 | @Test 101 | // tag::roles[] 102 | public void testRolesEndpoint() { 103 | // tag::adminRequest3[] 104 | Response response = makeRequest(urlRoles, authHeaderAdmin); 105 | // end::adminRequest3[] 106 | assertEquals(200, response.getStatus(), 107 | "Incorrect response code from " + urlRoles); 108 | assertEquals("[\"admin\",\"user\"]", response.readEntity(String.class), 109 | "Incorrect groups claim in token " + urlRoles); 110 | 111 | // tag::userRequest3[] 112 | response = makeRequest(urlRoles, authHeaderUser); 113 | // end::userRequest3[] 114 | assertEquals(200, response.getStatus(), 115 | "Incorrect response code from " + urlRoles); 116 | assertEquals("[\"user\"]", response.readEntity(String.class), 117 | "Incorrect groups claim in token " + urlRoles); 118 | 119 | // tag::nojwtRequest3[] 120 | response = makeRequest(urlRoles, null); 121 | // end::nojwtRequest3[] 122 | assertEquals(401, response.getStatus(), 123 | "Incorrect response code from " + urlRoles); 124 | 125 | response.close(); 126 | } 127 | // end::roles[] 128 | 129 | private Response makeRequest(String url, String authHeader) { 130 | try (Client client = ClientBuilder.newClient()) { 131 | Builder builder = client.target(url).request(); 132 | builder.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); 133 | if (authHeader != null) { 134 | builder.header(HttpHeaders.AUTHORIZATION, authHeader); 135 | } 136 | Response response = builder.get(); 137 | return response; 138 | } 139 | } 140 | 141 | } 142 | -------------------------------------------------------------------------------- /finish/system/src/test/java/it/io/openliberty/guides/system/util/JwtBuilder.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package it.io.openliberty.guides.system.util; 13 | 14 | import java.io.FileInputStream; 15 | import java.io.IOException; 16 | import java.security.GeneralSecurityException; 17 | import java.security.Key; 18 | import java.security.KeyStore; 19 | import java.util.Base64; 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | 23 | import io.vertx.core.Vertx; 24 | import io.vertx.core.json.JsonObject; 25 | import io.vertx.ext.auth.PubSecKeyOptions; 26 | import io.vertx.ext.auth.JWTOptions; 27 | import io.vertx.ext.auth.jwt.JWTAuth; 28 | import io.vertx.ext.auth.jwt.JWTAuthOptions; 29 | import io.vertx.core.json.JsonArray; 30 | 31 | public class JwtBuilder { 32 | 33 | private final String keystorePath = System.getProperty("user.dir") 34 | + "/target/liberty/wlp/usr/servers/" 35 | + "defaultServer/resources/security/key.p12"; 36 | 37 | private Vertx vertx = Vertx.vertx(); 38 | 39 | public String createUserJwt(String username) 40 | throws GeneralSecurityException, IOException { 41 | Set groups = new HashSet(); 42 | groups.add("user"); 43 | return createJwt(username, groups); 44 | } 45 | 46 | public String createAdminJwt(String username) 47 | throws GeneralSecurityException, IOException { 48 | Set groups = new HashSet(); 49 | groups.add("admin"); 50 | groups.add("user"); 51 | return createJwt(username, groups); 52 | } 53 | 54 | private String createJwt(String username, Set groups) throws IOException { 55 | JWTAuthOptions config = new JWTAuthOptions() 56 | .addPubSecKey(new PubSecKeyOptions() 57 | .setAlgorithm("RS256") 58 | .setBuffer(getPrivateKey())); 59 | 60 | JWTAuth provider = JWTAuth.create(vertx, config); 61 | 62 | io.vertx.core.json.JsonObject claimsObj = new JsonObject() 63 | .put("exp", (System.currentTimeMillis() / 1000) + 300) // Expire time 64 | .put("iat", (System.currentTimeMillis() / 1000)) // Issued time 65 | .put("jti", Long.toHexString(System.nanoTime())) // Unique value 66 | .put("sub", username) // Subject 67 | .put("upn", username) // Subject again 68 | .put("iss", "http://openliberty.io") 69 | .put("aud", "systemService") 70 | .put("groups", getGroupArray(groups)); 71 | 72 | String token = provider.generateToken(claimsObj, 73 | new JWTOptions().setAlgorithm("RS256")); 74 | 75 | return token; 76 | } 77 | 78 | private String getPrivateKey() throws IOException { 79 | try { 80 | KeyStore keystore = KeyStore.getInstance("PKCS12"); 81 | char[] password = new String("secret").toCharArray(); 82 | keystore.load(new FileInputStream(keystorePath), password); 83 | Key key = keystore.getKey("default", password); 84 | String output = "-----BEGIN PRIVATE KEY-----\n" 85 | + Base64.getEncoder().encodeToString(key.getEncoded()) + "\n" 86 | + "-----END PRIVATE KEY-----"; 87 | return output; 88 | } catch (Exception e) { 89 | e.printStackTrace(); 90 | } 91 | return ""; 92 | } 93 | 94 | private JsonArray getGroupArray(Set groups) { 95 | JsonArray arr = new JsonArray(); 96 | if (groups != null) { 97 | for (String group : groups) { 98 | arr.add(group); 99 | } 100 | } 101 | return arr; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /scripts/dailyBuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | while getopts t:d: flag; 3 | do 4 | case "${flag}" in 5 | t) DATE="${OPTARG}" ;; 6 | d) DRIVER="${OPTARG}" ;; 7 | *) echo "Invalid option" ;; 8 | esac 9 | done 10 | 11 | sed -i "\#liberty-maven-plugin#ahttps://public.dhe.ibm.com/ibmdl/export/pub/software/openliberty/runtime/nightly/$DATE/$DRIVER" system/pom.xml frontend/pom.xml 12 | cat system/pom.xml frontend/pom.xml 13 | 14 | ../scripts/testApp.sh 15 | -------------------------------------------------------------------------------- /scripts/testApp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | ./mvnw -version 4 | 5 | # LMP 3.0+ goals are listed here: https://github.com/OpenLiberty/ci.maven#goals 6 | 7 | ## Rebuild the application 8 | # package - Take the compiled code and package it in its distributable format. 9 | # liberty:create - Create a Liberty server. 10 | # liberty:install-feature - Install a feature packaged as a Subsystem Archive (esa) to the Liberty runtime. 11 | # liberty:deploy - Copy applications to the Liberty server's dropins or apps directory. 12 | ./mvnw -ntp -Dhttp.keepAlive=false \ 13 | -Dmaven.wagon.http.pool=false \ 14 | -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 \ 15 | -pl system -q clean package liberty:create liberty:install-feature liberty:deploy 16 | 17 | ## Run the tests 18 | # These commands are separated because if one of the commands fail, the test script will fail and exit. 19 | # e.g if liberty:start fails, then there is no need to run the failsafe commands. 20 | # liberty:start - Start a Liberty server in the background. 21 | # failsafe:integration-test - Runs the integration tests of an application. 22 | # liberty:stop - Stop a Liberty server. 23 | # failsafe:verify - Verifies that the integration tests of an application passed. 24 | ./mvnw -ntp -pl system liberty:start 25 | ./mvnw -ntp -Dhttp.keepAlive=false \ 26 | -Dmaven.wagon.http.pool=false \ 27 | -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 \ 28 | -pl system failsafe:integration-test 29 | ./mvnw -ntp -pl system liberty:stop 30 | ./mvnw -ntp -pl system failsafe:verify 31 | -------------------------------------------------------------------------------- /start/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/start/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /start/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar 3 | -------------------------------------------------------------------------------- /start/frontend/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | io.openliberty.guides 6 | frontend 7 | 1.0-SNAPSHOT 8 | war 9 | 10 | 11 | UTF-8 12 | UTF-8 13 | 11 14 | 11 15 | 9090 16 | 9091 17 | 18 | 19 | 20 | 21 | jakarta.platform 22 | jakarta.jakartaee-api 23 | 10.0.0 24 | provided 25 | 26 | 27 | org.eclipse.microprofile 28 | microprofile 29 | 7.0 30 | pom 31 | provided 32 | 33 | 34 | com.ibm.websphere.appserver.api 35 | com.ibm.websphere.appserver.api.jwt 36 | 1.1.101 37 | provided 38 | 39 | 40 | 41 | 42 | ${project.artifactId} 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-war-plugin 47 | 3.4.0 48 | 49 | 50 | io.openliberty.tools 51 | liberty-maven-plugin 52 | 3.11.3 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /start/frontend/src/main/java/io/openliberty/guides/frontend/LoginBean.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2018, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend; 13 | 14 | import java.util.Set; 15 | import java.util.HashSet; 16 | import jakarta.servlet.ServletException; 17 | import jakarta.servlet.http.HttpServletRequest; 18 | import jakarta.servlet.http.HttpSession; 19 | import jakarta.enterprise.context.ApplicationScoped; 20 | import jakarta.inject.Named; 21 | 22 | import com.ibm.websphere.security.jwt.JwtBuilder; 23 | import com.ibm.websphere.security.jwt.Claims; 24 | 25 | import io.openliberty.guides.frontend.util.SessionUtils; 26 | // tag::loginBean[] 27 | @ApplicationScoped 28 | @Named 29 | public class LoginBean { 30 | 31 | private String username; 32 | private String password; 33 | 34 | public void setUsername(String username) { 35 | this.username = username; 36 | } 37 | 38 | public void setPassword(String password) { 39 | this.password = password; 40 | } 41 | 42 | public String getUsername() { 43 | return username; 44 | } 45 | 46 | public String getPassword() { 47 | return password; 48 | } 49 | 50 | // tag::doLogin[] 51 | public String doLogin() throws Exception { 52 | HttpServletRequest request = SessionUtils.getRequest(); 53 | 54 | try { 55 | request.logout(); 56 | request.login(this.username, this.password); 57 | } catch (ServletException e) { 58 | System.out.println("Login failed."); 59 | return "error.jsf"; 60 | } 61 | 62 | String remoteUser = request.getRemoteUser(); 63 | Set roles = getRoles(request); 64 | if (remoteUser != null && remoteUser.equals(username)) { 65 | String jwt = buildJwt(username, roles); 66 | HttpSession ses = request.getSession(); 67 | if (ses == null) { 68 | System.out.println("Session timed out."); 69 | } else { 70 | // tag::setAttribute[] 71 | ses.setAttribute("jwt", jwt); 72 | // end::setAttribute[] 73 | } 74 | } else { 75 | System.out.println("Failed to update JWT in session."); 76 | } 77 | return "application.jsf?faces-redirect=true"; 78 | } 79 | // end::doLogin[] 80 | // tag::buildJwt[] 81 | 82 | private String buildJwt(String userName, Set roles) throws Exception { 83 | // tag::jwtBuilder[] 84 | return JwtBuilder.create("jwtFrontEndBuilder") 85 | // end::jwtBuilder[] 86 | .claim(Claims.SUBJECT, userName) 87 | .claim("upn", userName) 88 | // tag::groups[] 89 | .claim("groups", roles.toArray(new String[roles.size()])) 90 | // end::groups[] 91 | .claim("aud", "systemService") 92 | .buildJwt() 93 | .compact(); 94 | 95 | } 96 | // end::buildJwt[] 97 | 98 | private Set getRoles(HttpServletRequest request) { 99 | Set roles = new HashSet(); 100 | boolean isAdmin = request.isUserInRole("admin"); 101 | boolean isUser = request.isUserInRole("user"); 102 | if (isAdmin) { 103 | roles.add("admin"); 104 | } 105 | if (isUser) { 106 | roles.add("user"); 107 | } 108 | return roles; 109 | } 110 | } 111 | // end::loginBean[] 112 | -------------------------------------------------------------------------------- /start/frontend/src/main/java/io/openliberty/guides/frontend/client/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/start/frontend/src/main/java/io/openliberty/guides/frontend/client/.gitkeep -------------------------------------------------------------------------------- /start/frontend/src/main/java/io/openliberty/guides/frontend/filters/NoCacheFilter.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend.filters; 13 | 14 | import java.io.IOException; 15 | 16 | import jakarta.servlet.Filter; 17 | import jakarta.servlet.FilterChain; 18 | import jakarta.servlet.ServletException; 19 | import jakarta.servlet.ServletRequest; 20 | import jakarta.servlet.ServletResponse; 21 | import jakarta.servlet.annotation.WebFilter; 22 | import jakarta.servlet.http.HttpServletResponse; 23 | 24 | @WebFilter(servletNames = { "Faces Servlet" }) 25 | public class NoCacheFilter implements Filter { 26 | 27 | @Override 28 | public void doFilter(ServletRequest request, 29 | ServletResponse response, FilterChain chain) 30 | throws IOException, ServletException { 31 | HttpServletResponse httpServletResponse = 32 | (HttpServletResponse) response; 33 | httpServletResponse.setHeader("Cache-Control", 34 | "no-store, no-cache, must-revalidate, max-age=0"); 35 | httpServletResponse.setDateHeader("Expires", 0); 36 | httpServletResponse.setHeader("Pragma", "no-cache"); 37 | chain.doFilter(request, response); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /start/frontend/src/main/java/io/openliberty/guides/frontend/models/SystemModel.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.frontend.models; 13 | 14 | import jakarta.json.JsonObject; 15 | 16 | public class SystemModel { 17 | private String hostname; 18 | private String username; 19 | private String osName; 20 | 21 | public SystemModel(JsonObject jo) { 22 | hostname = jo.getString("hostname"); 23 | 24 | JsonObject props = jo.getJsonObject("properties"); 25 | username = props.getString("user.name"); 26 | osName = props.getString("os.name"); 27 | } 28 | 29 | public String getHostname() { 30 | return hostname; 31 | } 32 | 33 | public String getUsername() { 34 | return username; 35 | } 36 | 37 | public String getOsName() { 38 | return osName; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /start/frontend/src/main/java/io/openliberty/guides/frontend/util/SessionUtils.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2018, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | // tag::jwt[] 13 | package io.openliberty.guides.frontend.util; 14 | 15 | import jakarta.faces.context.FacesContext; 16 | import jakarta.servlet.http.HttpServletRequest; 17 | import jakarta.servlet.http.HttpSession; 18 | 19 | public class SessionUtils { 20 | // Gets the current session for a logged in user. 21 | public static HttpSession getSession() { 22 | return (HttpSession) FacesContext.getCurrentInstance().getExternalContext() 23 | .getSession(false); 24 | } 25 | 26 | // Gets Http servlet for user request information. 27 | public static HttpServletRequest getRequest() { 28 | return (HttpServletRequest) FacesContext.getCurrentInstance() 29 | .getExternalContext().getRequest(); 30 | } 31 | 32 | public static String getJwtToken() { 33 | return (String) getSession().getAttribute("jwt"); 34 | } 35 | 36 | } 37 | // end::jwt[] 38 | -------------------------------------------------------------------------------- /start/frontend/src/main/liberty/config/resources/security/key.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/start/frontend/src/main/liberty/config/resources/security/key.p12 -------------------------------------------------------------------------------- /start/frontend/src/main/liberty/config/server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jakartaee-10.0 6 | microprofile-7.0 7 | restfulWS 8 | jsonb 9 | jsonp 10 | faces 11 | cdi 12 | 13 | appSecurity 14 | servlet 15 | mpJwt 16 | mpConfig 17 | mpRestClient 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /start/frontend/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Liberty Project 6 | 7 | 10 | 11 | org.apache.myfaces.SECRET 12 | c3R1ZmZhbmQ= 13 | 14 | 15 | 16 | org.apache.myfaces.MAC_SECRET 17 | bW9yZXN0dWY= 18 | 19 | 20 | 21 | org.apache.myfaces.SERIALIZE_STATE_IN_SESSION 22 | false 23 | 24 | 25 | 40 | 41 | 42 | Faces Servlet 43 | jakarta.faces.webapp.FacesServlet 44 | 1 45 | 46 | 47 | 48 | 49 | Faces Servlet 50 | *.jsf 51 | 52 | 53 | 54 | index.jsf 55 | 56 | 57 | 58 | 59 | 60 | admin 61 | 62 | 63 | 64 | user 65 | 66 | 67 | 68 | 69 | 70 | 71 | ViewProperties 72 | /application.jsf 73 | GET 74 | 75 | 76 | user 77 | 78 | 79 | 80 | 81 | FORM 82 | WebRealm 83 | 84 | /login.jsf 85 | /error.jsf 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /start/frontend/src/main/webapp/application.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 23 | 24 | Application 25 | 62 | 63 | 64 | 65 |
66 | 67 | 68 |
69 |
70 | 71 | 72 | System Username: 73 | #{applicationBean.username} 74 | Current OS: 75 | #{applicationBean.os} 76 | Roles: 77 | #{applicationBean.jwtRoles} 78 | JSON Web Token: 79 | #{applicationBean.jwt} 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /start/frontend/src/main/webapp/error.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 23 | Security Login Error 24 | 25 | 26 |

A form login authentication failure occurred!

27 |

28 | The user name or password might be incorrect, or the user might not exist. 29 |

30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /start/frontend/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/start/frontend/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /start/frontend/src/main/webapp/index.xhtml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 |

Welcome to your Open Liberty application

16 |

Open Liberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. Find out more at openliberty.io.

17 |

Log in to try out the application.

18 |
19 |

Eclipse MicroProfile

20 |

21 | The Eclipse MicroProfile project is an open community with the aim of optimizing enterprise Java for a microservices architecture. 22 | MicroProfile evolves with guidance from the community. 23 |

24 |

25 | If you want to share your thoughts, you can post straight to the 26 | MicroProfile Google group. 27 |

28 |

29 | For more information about the features used in this application, see the Open Liberty documentation: 30 |

43 |

44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /start/frontend/src/main/webapp/login.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 23 | Security Login Page 24 | 25 |

Form Login

26 | 27 |

28 | Username 29 | 30 |

31 |

32 | Password 33 | 34 |

35 |

36 | 38 | 39 |

41 |

42 |
43 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /start/mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Apache Maven Wrapper startup batch script, version 3.3.2 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | # e.g. to debug Maven itself, use 32 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | # ---------------------------------------------------------------------------- 35 | 36 | if [ -z "$MAVEN_SKIP_RC" ]; then 37 | 38 | if [ -f /usr/local/etc/mavenrc ]; then 39 | . /usr/local/etc/mavenrc 40 | fi 41 | 42 | if [ -f /etc/mavenrc ]; then 43 | . /etc/mavenrc 44 | fi 45 | 46 | if [ -f "$HOME/.mavenrc" ]; then 47 | . "$HOME/.mavenrc" 48 | fi 49 | 50 | fi 51 | 52 | # OS specific support. $var _must_ be set to either true or false. 53 | cygwin=false 54 | darwin=false 55 | mingw=false 56 | case "$(uname)" in 57 | CYGWIN*) cygwin=true ;; 58 | MINGW*) mingw=true ;; 59 | Darwin*) 60 | darwin=true 61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 63 | if [ -z "$JAVA_HOME" ]; then 64 | if [ -x "/usr/libexec/java_home" ]; then 65 | JAVA_HOME="$(/usr/libexec/java_home)" 66 | export JAVA_HOME 67 | else 68 | JAVA_HOME="/Library/Java/Home" 69 | export JAVA_HOME 70 | fi 71 | fi 72 | ;; 73 | esac 74 | 75 | if [ -z "$JAVA_HOME" ]; then 76 | if [ -r /etc/gentoo-release ]; then 77 | JAVA_HOME=$(java-config --jre-home) 78 | fi 79 | fi 80 | 81 | # For Cygwin, ensure paths are in UNIX format before anything is touched 82 | if $cygwin; then 83 | [ -n "$JAVA_HOME" ] \ 84 | && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 85 | [ -n "$CLASSPATH" ] \ 86 | && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 87 | fi 88 | 89 | # For Mingw, ensure paths are in UNIX format before anything is touched 90 | if $mingw; then 91 | [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ 92 | && JAVA_HOME="$( 93 | cd "$JAVA_HOME" || ( 94 | echo "cannot cd into $JAVA_HOME." >&2 95 | exit 1 96 | ) 97 | pwd 98 | )" 99 | fi 100 | 101 | if [ -z "$JAVA_HOME" ]; then 102 | javaExecutable="$(which javac)" 103 | if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then 104 | # readlink(1) is not available as standard on Solaris 10. 105 | readLink=$(which readlink) 106 | if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then 107 | if $darwin; then 108 | javaHome="$(dirname "$javaExecutable")" 109 | javaExecutable="$(cd "$javaHome" && pwd -P)/javac" 110 | else 111 | javaExecutable="$(readlink -f "$javaExecutable")" 112 | fi 113 | javaHome="$(dirname "$javaExecutable")" 114 | javaHome=$(expr "$javaHome" : '\(.*\)/bin') 115 | JAVA_HOME="$javaHome" 116 | export JAVA_HOME 117 | fi 118 | fi 119 | fi 120 | 121 | if [ -z "$JAVACMD" ]; then 122 | if [ -n "$JAVA_HOME" ]; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ]; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD="$JAVA_HOME/jre/sh/java" 126 | else 127 | JAVACMD="$JAVA_HOME/bin/java" 128 | fi 129 | else 130 | JAVACMD="$( 131 | \unset -f command 2>/dev/null 132 | \command -v java 133 | )" 134 | fi 135 | fi 136 | 137 | if [ ! -x "$JAVACMD" ]; then 138 | echo "Error: JAVA_HOME is not defined correctly." >&2 139 | echo " We cannot execute $JAVACMD" >&2 140 | exit 1 141 | fi 142 | 143 | if [ -z "$JAVA_HOME" ]; then 144 | echo "Warning: JAVA_HOME environment variable is not set." >&2 145 | fi 146 | 147 | # traverses directory structure from process work directory to filesystem root 148 | # first directory with .mvn subdirectory is considered project base directory 149 | find_maven_basedir() { 150 | if [ -z "$1" ]; then 151 | echo "Path not specified to find_maven_basedir" >&2 152 | return 1 153 | fi 154 | 155 | basedir="$1" 156 | wdir="$1" 157 | while [ "$wdir" != '/' ]; do 158 | if [ -d "$wdir"/.mvn ]; then 159 | basedir=$wdir 160 | break 161 | fi 162 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 163 | if [ -d "${wdir}" ]; then 164 | wdir=$( 165 | cd "$wdir/.." || exit 1 166 | pwd 167 | ) 168 | fi 169 | # end of workaround 170 | done 171 | printf '%s' "$( 172 | cd "$basedir" || exit 1 173 | pwd 174 | )" 175 | } 176 | 177 | # concatenates all lines of a file 178 | concat_lines() { 179 | if [ -f "$1" ]; then 180 | # Remove \r in case we run on Windows within Git Bash 181 | # and check out the repository with auto CRLF management 182 | # enabled. Otherwise, we may read lines that are delimited with 183 | # \r\n and produce $'-Xarg\r' rather than -Xarg due to word 184 | # splitting rules. 185 | tr -s '\r\n' ' ' <"$1" 186 | fi 187 | } 188 | 189 | log() { 190 | if [ "$MVNW_VERBOSE" = true ]; then 191 | printf '%s\n' "$1" 192 | fi 193 | } 194 | 195 | BASE_DIR=$(find_maven_basedir "$(dirname "$0")") 196 | if [ -z "$BASE_DIR" ]; then 197 | exit 1 198 | fi 199 | 200 | MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 201 | export MAVEN_PROJECTBASEDIR 202 | log "$MAVEN_PROJECTBASEDIR" 203 | 204 | ########################################################################################## 205 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 206 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 207 | ########################################################################################## 208 | wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" 209 | if [ -r "$wrapperJarPath" ]; then 210 | log "Found $wrapperJarPath" 211 | else 212 | log "Couldn't find $wrapperJarPath, downloading it ..." 213 | 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 216 | else 217 | wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 218 | fi 219 | while IFS="=" read -r key value; do 220 | # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) 221 | safeValue=$(echo "$value" | tr -d '\r') 222 | case "$key" in wrapperUrl) 223 | wrapperUrl="$safeValue" 224 | break 225 | ;; 226 | esac 227 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 228 | log "Downloading from: $wrapperUrl" 229 | 230 | if $cygwin; then 231 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 232 | fi 233 | 234 | if command -v wget >/dev/null; then 235 | log "Found wget ... using wget" 236 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" 237 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 238 | wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 239 | else 240 | wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 241 | fi 242 | elif command -v curl >/dev/null; then 243 | log "Found curl ... using curl" 244 | [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" 245 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 246 | curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 247 | else 248 | curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 249 | fi 250 | else 251 | log "Falling back to using Java to download" 252 | javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" 253 | javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" 254 | # For Cygwin, switch paths to Windows format before running javac 255 | if $cygwin; then 256 | javaSource=$(cygpath --path --windows "$javaSource") 257 | javaClass=$(cygpath --path --windows "$javaClass") 258 | fi 259 | if [ -e "$javaSource" ]; then 260 | if [ ! -e "$javaClass" ]; then 261 | log " - Compiling MavenWrapperDownloader.java ..." 262 | ("$JAVA_HOME/bin/javac" "$javaSource") 263 | fi 264 | if [ -e "$javaClass" ]; then 265 | log " - Running MavenWrapperDownloader.java ..." 266 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" 267 | fi 268 | fi 269 | fi 270 | fi 271 | ########################################################################################## 272 | # End of extension 273 | ########################################################################################## 274 | 275 | # If specified, validate the SHA-256 sum of the Maven wrapper jar file 276 | wrapperSha256Sum="" 277 | while IFS="=" read -r key value; do 278 | case "$key" in wrapperSha256Sum) 279 | wrapperSha256Sum=$value 280 | break 281 | ;; 282 | esac 283 | done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 284 | if [ -n "$wrapperSha256Sum" ]; then 285 | wrapperSha256Result=false 286 | if command -v sha256sum >/dev/null; then 287 | if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then 288 | wrapperSha256Result=true 289 | fi 290 | elif command -v shasum >/dev/null; then 291 | if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then 292 | wrapperSha256Result=true 293 | fi 294 | else 295 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 296 | echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 297 | exit 1 298 | fi 299 | if [ $wrapperSha256Result = false ]; then 300 | echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 301 | echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 302 | echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 303 | exit 1 304 | fi 305 | fi 306 | 307 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 308 | 309 | # For Cygwin, switch paths to Windows format before running java 310 | if $cygwin; then 311 | [ -n "$JAVA_HOME" ] \ 312 | && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 313 | [ -n "$CLASSPATH" ] \ 314 | && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 315 | [ -n "$MAVEN_PROJECTBASEDIR" ] \ 316 | && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 317 | fi 318 | 319 | # Provide a "standardized" way to retrieve the CLI args that will 320 | # work with both Windows and non-Windows executions. 321 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" 322 | export MAVEN_CMD_LINE_ARGS 323 | 324 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 325 | 326 | # shellcheck disable=SC2086 # safe args 327 | exec "$JAVACMD" \ 328 | $MAVEN_OPTS \ 329 | $MAVEN_DEBUG_OPTS \ 330 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 331 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 332 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 333 | -------------------------------------------------------------------------------- /start/mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Apache Maven Wrapper startup batch script, version 3.3.2 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 28 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending 29 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 30 | @REM e.g. to debug Maven itself, use 31 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 32 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 33 | @REM ---------------------------------------------------------------------------- 34 | 35 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 36 | @echo off 37 | @REM set title of command window 38 | title %0 39 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 40 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 41 | 42 | @REM set %HOME% to equivalent of $HOME 43 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 44 | 45 | @REM Execute a user defined script before this one 46 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 47 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 48 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* 49 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* 50 | :skipRcPre 51 | 52 | @setlocal 53 | 54 | set ERROR_CODE=0 55 | 56 | @REM To isolate internal variables from possible post scripts, we use another setlocal 57 | @setlocal 58 | 59 | @REM ==== START VALIDATION ==== 60 | if not "%JAVA_HOME%" == "" goto OkJHome 61 | 62 | echo. >&2 63 | echo Error: JAVA_HOME not found in your environment. >&2 64 | echo Please set the JAVA_HOME variable in your environment to match the >&2 65 | echo location of your Java installation. >&2 66 | echo. >&2 67 | goto error 68 | 69 | :OkJHome 70 | if exist "%JAVA_HOME%\bin\java.exe" goto init 71 | 72 | echo. >&2 73 | echo Error: JAVA_HOME is set to an invalid directory. >&2 74 | echo JAVA_HOME = "%JAVA_HOME%" >&2 75 | echo Please set the JAVA_HOME variable in your environment to match the >&2 76 | echo location of your Java installation. >&2 77 | echo. >&2 78 | goto error 79 | 80 | @REM ==== END VALIDATION ==== 81 | 82 | :init 83 | 84 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 85 | @REM Fallback to current working directory if not found. 86 | 87 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 88 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 89 | 90 | set EXEC_DIR=%CD% 91 | set WDIR=%EXEC_DIR% 92 | :findBaseDir 93 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 94 | cd .. 95 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 96 | set WDIR=%CD% 97 | goto findBaseDir 98 | 99 | :baseDirFound 100 | set MAVEN_PROJECTBASEDIR=%WDIR% 101 | cd "%EXEC_DIR%" 102 | goto endDetectBaseDir 103 | 104 | :baseDirNotFound 105 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 106 | cd "%EXEC_DIR%" 107 | 108 | :endDetectBaseDir 109 | 110 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 111 | 112 | @setlocal EnableExtensions EnableDelayedExpansion 113 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 114 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 115 | 116 | :endReadAdditionalConfig 117 | 118 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 123 | 124 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 125 | IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B 126 | ) 127 | 128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 130 | if exist %WRAPPER_JAR% ( 131 | if "%MVNW_VERBOSE%" == "true" ( 132 | echo Found %WRAPPER_JAR% 133 | ) 134 | ) else ( 135 | if not "%MVNW_REPOURL%" == "" ( 136 | SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" 137 | ) 138 | if "%MVNW_VERBOSE%" == "true" ( 139 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 140 | echo Downloading from: %WRAPPER_URL% 141 | ) 142 | 143 | powershell -Command "&{"^ 144 | "$webclient = new-object System.Net.WebClient;"^ 145 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 146 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 147 | "}"^ 148 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ 149 | "}" 150 | if "%MVNW_VERBOSE%" == "true" ( 151 | echo Finished downloading %WRAPPER_JAR% 152 | ) 153 | ) 154 | @REM End of extension 155 | 156 | @REM If specified, validate the SHA-256 sum of the Maven wrapper jar file 157 | SET WRAPPER_SHA_256_SUM="" 158 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 159 | IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B 160 | ) 161 | IF NOT %WRAPPER_SHA_256_SUM%=="" ( 162 | powershell -Command "&{"^ 163 | "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ 164 | "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ 165 | "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ 166 | " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ 167 | " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ 168 | " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ 169 | " exit 1;"^ 170 | "}"^ 171 | "}" 172 | if ERRORLEVEL 1 goto error 173 | ) 174 | 175 | @REM Provide a "standardized" way to retrieve the CLI args that will 176 | @REM work with both Windows and non-Windows executions. 177 | set MAVEN_CMD_LINE_ARGS=%* 178 | 179 | %MAVEN_JAVA_EXE% ^ 180 | %JVM_CONFIG_MAVEN_PROPS% ^ 181 | %MAVEN_OPTS% ^ 182 | %MAVEN_DEBUG_OPTS% ^ 183 | -classpath %WRAPPER_JAR% ^ 184 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ 185 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 186 | if ERRORLEVEL 1 goto error 187 | goto end 188 | 189 | :error 190 | set ERROR_CODE=1 191 | 192 | :end 193 | @endlocal & set ERROR_CODE=%ERROR_CODE% 194 | 195 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost 196 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 197 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" 198 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" 199 | :skipRcPost 200 | 201 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 202 | if "%MAVEN_BATCH_PAUSE%"=="on" pause 203 | 204 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% 205 | 206 | cmd /C exit /B %ERROR_CODE% 207 | -------------------------------------------------------------------------------- /start/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | io.openliberty.guides 9 | guide-microprofile-jwt 10 | 1.0-SNAPSHOT 11 | pom 12 | 13 | 14 | frontend 15 | system 16 | 17 | -------------------------------------------------------------------------------- /start/system/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 4.0.0 7 | 8 | io.openliberty.guides 9 | system 10 | 1.0-SNAPSHOT 11 | war 12 | 13 | 14 | UTF-8 15 | UTF-8 16 | 11 17 | 11 18 | 19 | localhost 20 | 8080 21 | 8443 22 | http://openliberty.io 23 | 24 | 25 | 26 | 27 | 28 | jakarta.platform 29 | jakarta.jakartaee-api 30 | 10.0.0 31 | provided 32 | 33 | 34 | org.eclipse.microprofile 35 | 36 | microprofile 37 | 38 | 7.0 39 | pom 40 | provided 41 | 42 | 43 | 44 | org.apache.commons 45 | commons-lang3 46 | 3.17.0 47 | 48 | 49 | 50 | org.junit.jupiter 51 | junit-jupiter 52 | 5.13.0 53 | test 54 | 55 | 56 | org.jboss.resteasy 57 | resteasy-client 58 | 6.2.12.Final 59 | test 60 | 61 | 62 | org.jboss.resteasy 63 | resteasy-json-binding-provider 64 | 6.2.12.Final 65 | test 66 | 67 | 68 | org.glassfish 69 | jakarta.json 70 | 2.0.1 71 | test 72 | 73 | 74 | io.vertx 75 | vertx-auth-jwt 76 | 5.0.0 77 | test 78 | 79 | 80 | io.netty 81 | netty-resolver-dns-native-macos 82 | 4.1.119.Final 83 | osx-x86_64 84 | test 85 | 86 | 87 | 88 | 89 | ${project.artifactId} 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-war-plugin 94 | 3.4.0 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-surefire-plugin 100 | 3.5.3 101 | 102 | 103 | 104 | io.openliberty.tools 105 | liberty-maven-plugin 106 | 3.11.3 107 | 108 | 109 | 110 | org.apache.maven.plugins 111 | maven-failsafe-plugin 112 | 3.5.3 113 | 114 | 115 | ${liberty.var.default.hostname} 116 | ${liberty.var.http.port} 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /start/system/src/main/java/io/openliberty/guides/system/SystemApplication.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2017, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package io.openliberty.guides.system; 13 | 14 | import jakarta.ws.rs.core.Application; 15 | import jakarta.ws.rs.ApplicationPath; 16 | 17 | @ApplicationPath("system") 18 | public class SystemApplication extends Application { 19 | 20 | } 21 | -------------------------------------------------------------------------------- /start/system/src/main/liberty/config/resources/security/key.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/start/system/src/main/liberty/config/resources/security/key.p12 -------------------------------------------------------------------------------- /start/system/src/main/liberty/config/server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | jakartaee-10.0 5 | microprofile-7.0 6 | restfulWS 7 | jsonb 8 | jsonp 9 | cdi 10 | mpConfig 11 | mpRestClient 12 | appSecurity 13 | servlet 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /start/system/src/main/resources/META-INF/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/start/system/src/main/resources/META-INF/.gitkeep -------------------------------------------------------------------------------- /start/system/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | Liberty Project 6 | 7 | 8 | index.html 9 | 10 | -------------------------------------------------------------------------------- /start/system/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLiberty/guide-microprofile-jwt/bf85890f1e6cdbdfe7126a8820bba08be4fb4beb/start/system/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /start/system/src/main/webapp/index.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 |

Welcome to your Open Liberty application

19 |

Open Liberty is a lightweight open framework for building fast and efficient cloud-native Java microservices. Find out more at openliberty.io.

20 |
21 |

Eclipse MicroProfile

22 |

23 | The Eclipse MicroProfile project is an open community with the aim of optimizing enterprise Java for a microservices architecture. 24 | MicroProfile evolves with guidance from the community. 25 |

26 |

27 | If you want to share your thoughts, you can post straight to the 28 | MicroProfile Google group. 29 |

30 |

31 | For more information about the features used in this application, see the Open Liberty documentation: 32 |

44 |

45 |
46 | 47 | -------------------------------------------------------------------------------- /start/system/src/test/java/it/io/openliberty/guides/system/util/JwtBuilder.java: -------------------------------------------------------------------------------- 1 | // tag::copyright[] 2 | /******************************************************************************* 3 | * Copyright (c) 2020, 2022 IBM Corporation and others. 4 | * All rights reserved. This program and the accompanying materials 5 | * are made available under the terms of the Eclipse Public License 2.0 6 | * which accompanies this distribution, and is available at 7 | * http://www.eclipse.org/legal/epl-2.0/ 8 | * 9 | * SPDX-License-Identifier: EPL-2.0 10 | *******************************************************************************/ 11 | // end::copyright[] 12 | package it.io.openliberty.guides.system.util; 13 | 14 | import java.io.FileInputStream; 15 | import java.io.IOException; 16 | import java.security.GeneralSecurityException; 17 | import java.security.Key; 18 | import java.security.KeyStore; 19 | import java.util.Base64; 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | 23 | import io.vertx.core.Vertx; 24 | import io.vertx.core.json.JsonObject; 25 | import io.vertx.ext.auth.PubSecKeyOptions; 26 | import io.vertx.ext.auth.JWTOptions; 27 | import io.vertx.ext.auth.jwt.JWTAuth; 28 | import io.vertx.ext.auth.jwt.JWTAuthOptions; 29 | import io.vertx.core.json.JsonArray; 30 | 31 | public class JwtBuilder { 32 | 33 | private final String keystorePath = System.getProperty("user.dir") 34 | + "/target/liberty/wlp/usr/servers/" 35 | + "defaultServer/resources/security/key.p12"; 36 | 37 | private Vertx vertx = Vertx.vertx(); 38 | 39 | public String createUserJwt(String username) 40 | throws GeneralSecurityException, IOException { 41 | Set groups = new HashSet(); 42 | groups.add("user"); 43 | return createJwt(username, groups); 44 | } 45 | 46 | public String createAdminJwt(String username) 47 | throws GeneralSecurityException, IOException { 48 | Set groups = new HashSet(); 49 | groups.add("admin"); 50 | groups.add("user"); 51 | return createJwt(username, groups); 52 | } 53 | 54 | private String createJwt(String username, Set groups) throws IOException { 55 | JWTAuthOptions config = new JWTAuthOptions() 56 | .addPubSecKey(new PubSecKeyOptions() 57 | .setAlgorithm("RS256") 58 | .setBuffer(getPrivateKey())); 59 | 60 | JWTAuth provider = JWTAuth.create(vertx, config); 61 | 62 | io.vertx.core.json.JsonObject claimsObj = new JsonObject() 63 | .put("exp", (System.currentTimeMillis() / 1000) + 300) // Expire time 64 | .put("iat", (System.currentTimeMillis() / 1000)) // Issued time 65 | .put("jti", Long.toHexString(System.nanoTime())) // Unique value 66 | .put("sub", username) // Subject 67 | .put("upn", username) // Subject again 68 | .put("iss", "http://openliberty.io") 69 | .put("aud", "systemService") 70 | .put("groups", getGroupArray(groups)); 71 | 72 | String token = provider.generateToken(claimsObj, 73 | new JWTOptions().setAlgorithm("RS256")); 74 | 75 | return token; 76 | } 77 | 78 | private String getPrivateKey() throws IOException { 79 | try { 80 | KeyStore keystore = KeyStore.getInstance("PKCS12"); 81 | char[] password = new String("secret").toCharArray(); 82 | keystore.load(new FileInputStream(keystorePath), password); 83 | Key key = keystore.getKey("default", password); 84 | String output = "-----BEGIN PRIVATE KEY-----\n" 85 | + Base64.getEncoder().encodeToString(key.getEncoded()) + "\n" 86 | + "-----END PRIVATE KEY-----"; 87 | return output; 88 | } catch (Exception e) { 89 | e.printStackTrace(); 90 | } 91 | return ""; 92 | } 93 | 94 | private JsonArray getGroupArray(Set groups) { 95 | JsonArray arr = new JsonArray(); 96 | if (groups != null) { 97 | for (String group : groups) { 98 | arr.add(group); 99 | } 100 | } 101 | return arr; 102 | } 103 | 104 | } 105 | --------------------------------------------------------------------------------